summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/opengl')
-rw-r--r--src/opengl/.prev_CMakeLists.txt62
-rw-r--r--src/opengl/CMakeLists.txt63
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qgl.cpp182
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp60
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglcolormap.cpp71
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp86
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglpixelbuffer.cpp69
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qglshaderprogram.cpp104
-rw-r--r--src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp95
-rw-r--r--src/opengl/doc/src/qtopengl-examples.qdoc9
-rw-r--r--src/opengl/doc/src/qtopengl-module.qdoc13
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp875
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h523
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp414
-rw-r--r--src/opengl/opengl.pro97
-rw-r--r--src/opengl/qgl.cpp5558
-rw-r--r--src/opengl/qgl.h524
-rw-r--r--src/opengl/qgl_p.h556
-rw-r--r--src/opengl/qglbuffer.cpp568
-rw-r--r--src/opengl/qglbuffer.h125
-rw-r--r--src/opengl/qglcolormap.cpp296
-rw-r--r--src/opengl/qglframebufferobject.cpp1466
-rw-r--r--src/opengl/qglframebufferobject.h149
-rw-r--r--src/opengl/qglframebufferobject_p.h157
-rw-r--r--src/opengl/qglfunctions.cpp1330
-rw-r--r--src/opengl/qglfunctions.h1688
-rw-r--r--src/opengl/qglpaintdevice.cpp239
-rw-r--r--src/opengl/qglpixelbuffer.cpp654
-rw-r--r--src/opengl/qglpixelbuffer.h104
-rw-r--r--src/opengl/qglpixelbuffer_p.h107
-rw-r--r--src/opengl/qglshaderprogram.cpp3237
-rw-r--r--src/opengl/qglshaderprogram.h303
-rw-r--r--src/opengl/qgraphicsshadereffect.cpp272
-rw-r--r--src/opengl/qopengl2pexvertexarray.cpp (renamed from src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp)20
-rw-r--r--src/opengl/qopengl2pexvertexarray_p.h (renamed from src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h)52
-rw-r--r--src/opengl/qopenglcustomshaderstage.cpp (renamed from src/opengl/gl2paintengineex/qglcustomshaderstage.cpp)62
-rw-r--r--src/opengl/qopenglcustomshaderstage_p.h (renamed from src/opengl/gl2paintengineex/qglcustomshaderstage_p.h)24
-rw-r--r--src/opengl/qopengldebug.cpp1826
-rw-r--r--src/opengl/qopengldebug.h221
-rw-r--r--src/opengl/qopenglengineshadermanager.cpp898
-rw-r--r--src/opengl/qopenglengineshadermanager_p.h (renamed from src/opengl/gl2paintengineex/qglengineshadermanager_p.h)212
-rw-r--r--src/opengl/qopenglengineshadersource_p.h969
-rw-r--r--src/opengl/qopenglgradientcache.cpp (renamed from src/opengl/gl2paintengineex/qglgradientcache.cpp)135
-rw-r--r--src/opengl/qopenglgradientcache_p.h (renamed from src/opengl/gl2paintengineex/qglgradientcache_p.h)28
-rw-r--r--src/opengl/qopenglpaintdevice.cpp372
-rw-r--r--src/opengl/qopenglpaintdevice.h95
-rw-r--r--src/opengl/qopenglpaintdevice_p.h87
-rw-r--r--src/opengl/qopenglpaintengine.cpp (renamed from src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp)1629
-rw-r--r--src/opengl/qopenglpaintengine_p.h (renamed from src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h)193
-rw-r--r--src/opengl/qopenglpixeltransferoptions.cpp263
-rw-r--r--src/opengl/qopenglpixeltransferoptions.h100
-rw-r--r--src/opengl/qopenglqueryhelper_p.h186
-rw-r--r--src/opengl/qopenglshadercache_p.h (renamed from src/opengl/gl2paintengineex/qglshadercache_p.h)14
-rw-r--r--src/opengl/qopengltexture.cpp4989
-rw-r--r--src/opengl/qopengltexture.h663
-rw-r--r--src/opengl/qopengltexture_p.h184
-rw-r--r--src/opengl/qopengltextureblitter.cpp682
-rw-r--r--src/opengl/qopengltextureblitter.h (renamed from src/opengl/qglcolormap.h)73
-rw-r--r--src/opengl/qopengltexturecache.cpp198
-rw-r--r--src/opengl/qopengltexturecache_p.h108
-rw-r--r--src/opengl/qopengltextureglyphcache.cpp485
-rw-r--r--src/opengl/qopengltextureglyphcache_p.h (renamed from src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h)78
-rw-r--r--src/opengl/qopengltexturehelper.cpp589
-rw-r--r--src/opengl/qopengltexturehelper_p.h797
-rw-r--r--src/opengl/qopengltextureuploader.cpp381
-rw-r--r--src/opengl/qopengltextureuploader_p.h (renamed from src/opengl/qgraphicsshadereffect_p.h)48
-rw-r--r--src/opengl/qopengltimerquery.cpp880
-rw-r--r--src/opengl/qopengltimerquery.h116
-rw-r--r--src/opengl/qopenglwidget.cpp1473
-rw-r--r--src/opengl/qopenglwidget.h (renamed from src/opengl/qglpaintdevice_p.h)102
-rw-r--r--src/opengl/qopenglwindow.cpp698
-rw-r--r--src/opengl/qopenglwindow.h107
72 files changed, 19035 insertions, 21058 deletions
diff --git a/src/opengl/.prev_CMakeLists.txt b/src/opengl/.prev_CMakeLists.txt
new file mode 100644
index 0000000000..eb125273bc
--- /dev/null
+++ b/src/opengl/.prev_CMakeLists.txt
@@ -0,0 +1,62 @@
+# Generated from opengl.pro.
+
+#####################################################################
+## OpenGL Module:
+#####################################################################
+
+qt_add_module(OpenGL
+ SOURCES
+ qopengl2pexvertexarray.cpp qopengl2pexvertexarray_p.h
+ qopenglcustomshaderstage.cpp qopenglcustomshaderstage_p.h
+ qopengldebug.cpp qopengldebug.h
+ qopenglengineshadermanager.cpp qopenglengineshadermanager_p.h
+ qopenglengineshadersource_p.h
+ qopenglgradientcache.cpp qopenglgradientcache_p.h
+ qopenglpaintdevice.cpp qopenglpaintdevice.h qopenglpaintdevice_p.h
+ qopenglpaintengine.cpp qopenglpaintengine_p.h
+ qopenglpixeltransferoptions.cpp qopenglpixeltransferoptions.h
+ qopenglshadercache_p.h
+ qopengltexture.cpp qopengltexture.h qopengltexture_p.h
+ qopengltexturecache.cpp qopengltexturecache_p.h
+ qopengltextureglyphcache.cpp qopengltextureglyphcache_p.h
+ qopengltexturehelper.cpp qopengltexturehelper_p.h
+ qopengltextureuploader.cpp qopengltextureuploader_p.h
+ qopenglwindow.cpp qopenglwindow.h
+ qtopenglglobal.h
+ DEFINES
+ QT_NO_FOREACH
+ QT_NO_USING_NAMESPACE
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::GuiPrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::Gui
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+ Qt::GuiPrivate
+)
+
+## Scopes:
+#####################################################################
+
+qt_extend_target(OpenGL CONDITION QT_FEATURE_widgets
+ SOURCES
+ qopenglwidget.cpp qopenglwidget.h
+ LIBRARIES
+ Qt::WidgetsPrivate
+ PUBLIC_LIBRARIES
+ Qt::Widgets
+ PRIVATE_MODULE_INTERFACE
+ Qt::WidgetsPrivate
+)
+
+qt_extend_target(OpenGL CONDITION NOT QT_FEATURE_opengles2
+ SOURCES
+ qopenglqueryhelper_p.h
+ qopengltimerquery.cpp qopengltimerquery.h
+)
+qt_add_docs(OpenGL
+ doc/qtopengl.qdocconf
+)
+
diff --git a/src/opengl/CMakeLists.txt b/src/opengl/CMakeLists.txt
new file mode 100644
index 0000000000..acad98a681
--- /dev/null
+++ b/src/opengl/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Generated from opengl.pro.
+
+#####################################################################
+## OpenGL Module:
+#####################################################################
+
+qt_add_module(OpenGL
+ SOURCES
+ qopengl2pexvertexarray.cpp qopengl2pexvertexarray_p.h
+ qopenglcustomshaderstage.cpp qopenglcustomshaderstage_p.h
+ qopengldebug.cpp qopengldebug.h
+ qopenglengineshadermanager.cpp qopenglengineshadermanager_p.h
+ qopenglengineshadersource_p.h
+ qopenglgradientcache.cpp qopenglgradientcache_p.h
+ qopenglpaintdevice.cpp qopenglpaintdevice.h qopenglpaintdevice_p.h
+ qopenglpaintengine.cpp qopenglpaintengine_p.h
+ qopenglpixeltransferoptions.cpp qopenglpixeltransferoptions.h
+ qopenglshadercache_p.h
+ qopengltexture.cpp qopengltexture.h qopengltexture_p.h
+ qopengltextureblitter.cpp qopengltextureblitter.h
+ qopengltexturecache.cpp qopengltexturecache_p.h
+ qopengltextureglyphcache.cpp qopengltextureglyphcache_p.h
+ qopengltexturehelper.cpp qopengltexturehelper_p.h
+ qopengltextureuploader.cpp qopengltextureuploader_p.h
+ qopenglwindow.cpp qopenglwindow.h
+ qtopenglglobal.h
+ DEFINES
+ QT_NO_FOREACH
+ QT_NO_USING_NAMESPACE
+ LIBRARIES
+ Qt::CorePrivate
+ Qt::GuiPrivate
+ PUBLIC_LIBRARIES
+ Qt::Core
+ Qt::Gui
+ PRIVATE_MODULE_INTERFACE
+ Qt::CorePrivate
+ Qt::GuiPrivate
+)
+
+## Scopes:
+#####################################################################
+
+qt_extend_target(OpenGL CONDITION QT_FEATURE_widgets
+ SOURCES
+ qopenglwidget.cpp qopenglwidget.h
+ LIBRARIES
+ Qt::WidgetsPrivate
+ PUBLIC_LIBRARIES
+ Qt::Widgets
+ PRIVATE_MODULE_INTERFACE
+ Qt::WidgetsPrivate
+)
+
+qt_extend_target(OpenGL CONDITION NOT QT_FEATURE_opengles2
+ SOURCES
+ qopenglqueryhelper_p.h
+ qopengltimerquery.cpp qopengltimerquery.h
+)
+qt_add_docs(OpenGL
+ doc/qtopengl.qdocconf
+)
+
diff --git a/src/opengl/doc/snippets/code/src_opengl_qgl.cpp b/src/opengl/doc/snippets/code/src_opengl_qgl.cpp
deleted file mode 100644
index a73ee2cdc5..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qgl.cpp
+++ /dev/null
@@ -1,182 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-QGLFormat fmt;
-fmt.setAlpha(true);
-fmt.setStereo(true);
-QGLFormat::setDefaultFormat(fmt);
-//! [0]
-
-
-//! [1]
-QGLFormat fmt;
-fmt.setDoubleBuffer(false); // single buffer
-fmt.setDirectRendering(false); // software rendering
-MyGLWidget* myWidget = new MyGLWidget(fmt, ...);
-//! [1]
-
-
-//! [2]
-QGLFormat fmt;
-fmt.setOverlay(true);
-fmt.setStereo(true);
-MyGLWidget* myWidget = new MyGLWidget(fmt, ...);
-if (!myWidget->format().stereo()) {
- // ok, goggles off
- if (!myWidget->format().hasOverlay()) {
- qFatal("Cool hardware required");
- }
-}
-//! [2]
-
-
-//! [3]
-// The rendering in MyGLWidget depends on using
-// stencil buffer and alpha channel
-MyGLWidget::MyGLWidget(QWidget* parent)
- : QGLWidget(QGLFormat(QGL::StencilBuffer | QGL::AlphaChannel), parent)
-{
- if (!format().stencil())
- qWarning("Could not get stencil buffer; results will be suboptimal");
- if (!format().alpha())
- qWarning("Could not get alpha channel; results will be suboptimal");
- ...
-}
-//! [3]
-
-
-//! [4]
-QApplication a(argc, argv);
-QGLFormat f;
-f.setDoubleBuffer(false);
-QGLFormat::setDefaultFormat(f);
-//! [4]
-
-
-//! [5]
-QGLFormat f = QGLFormat::defaultOverlayFormat();
-f.setDoubleBuffer(true);
-QGLFormat::setDefaultOverlayFormat(f);
-//! [5]
-
-
-//! [6]
-// ...continued from above
-MyGLWidget* myWidget = new MyGLWidget(QGLFormat(QGL::HasOverlay), ...);
-if (myWidget->format().hasOverlay()) {
- // Yes, we got an overlay, let's check _its_ format:
- QGLContext* olContext = myWidget->overlayContext();
- if (olContext->format().doubleBuffer())
- ; // yes, we got a double buffered overlay
- else
- ; // no, only single buffered overlays are available
-}
-//! [6]
-
-
-//! [7]
-QGLContext *cx;
-// ...
-QGLFormat f;
-f.setStereo(true);
-cx->setFormat(f);
-if (!cx->create())
- exit(); // no OpenGL support, or cannot render on the specified paintdevice
-if (!cx->format().stereo())
- exit(); // could not create stereo context
-//! [7]
-
-
-//! [8]
-class MyGLDrawer : public QGLWidget
-{
- Q_OBJECT // must include this if you use Qt signals/slots
-
-public:
- MyGLDrawer(QWidget *parent)
- : QGLWidget(parent) {}
-
-protected:
-
- void initializeGL() override
- {
- // Set up the rendering context, define display lists etc.:
- ...
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glEnable(GL_DEPTH_TEST);
- ...
- }
-
- void resizeGL(int w, int h) override
- {
- // setup viewport, projection etc.:
- glViewport(0, 0, (GLint)w, (GLint)h);
- ...
- glFrustum(...);
- ...
- }
-
- void paintGL() override
- {
- // draw the scene:
- ...
- glRotatef(...);
- glMaterialfv(...);
- glBegin(GL_QUADS);
- glVertex3f(...);
- glVertex3f(...);
- ...
- glEnd();
- ...
- }
-
-};
-//! [8]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp b/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp
deleted file mode 100644
index 11ef88ab37..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qglbuffer.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
- QGLBuffer buffer1(QGLBuffer::IndexBuffer);
- buffer1.create();
-
- QGLBuffer buffer2 = buffer1;
-//! [0]
-
-//! [1]
- QGLBuffer::release(QGLBuffer::VertexBuffer);
-//! [1]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglcolormap.cpp b/src/opengl/doc/snippets/code/src_opengl_qglcolormap.cpp
deleted file mode 100644
index 12a089944f..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qglcolormap.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-#include <QApplication>
-#include <QGLColormap>
-
-int main()
-{
- QApplication app(argc, argv);
-
- MySuperGLWidget widget; // a QGLWidget in color-index mode
- QGLColormap colormap;
-
- // This will fill the colormap with colors ranging from
- // black to white.
- for (int i = 0; i < colormap.size(); i++)
- colormap.setEntry(i, qRgb(i, i, i));
-
- widget.setColormap(colormap);
- widget.show();
- return app.exec();
-}
-//! [0]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp b/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp
deleted file mode 100644
index c848ae7ede..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qglfunctions.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
- class MyGLWidget : public QGLWidget, protected QGLFunctions
- {
- Q_OBJECT
- public:
- MyGLWidget(QWidget *parent = 0) : QGLWidget(parent) {}
-
- protected:
- void initializeGL();
- void paintGL();
- };
-
- void MyGLWidget::initializeGL()
- {
- initializeGLFunctions();
- }
-//! [0]
-
-//! [1]
- void MyGLWidget::paintGL()
- {
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, textureId);
- ...
- }
-//! [1]
-
-//! [2]
- QGLFunctions glFuncs(QGLContext::currentContext());
- glFuncs.glActiveTexture(GL_TEXTURE1);
-//! [2]
-
-//! [3]
- QGLFunctions funcs(QGLContext::currentContext());
- bool npot = funcs.hasOpenGLFeature(QGLFunctions::NPOTTextures);
-//! [3]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglpixelbuffer.cpp b/src/opengl/doc/snippets/code/src_opengl_qglpixelbuffer.cpp
deleted file mode 100644
index f6fbe6ddb4..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qglpixelbuffer.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-QGLPixelBuffer pbuffer(...);
-...
-pbuffer.makeCurrent();
-GLuint dynamicTexture = pbuffer.generateDynamicTexture();
-pbuffer.bindToDynamicTexture(dynamicTexture);
-...
-pbuffer.releaseFromDynamicTexture();
-//! [0]
-
-
-//! [1]
-QGLPixelBuffer pbuffer(...);
-...
-pbuffer.makeCurrent();
-GLuint dynamicTexture = pbuffer.generateDynamicTexture();
-...
-pbuffer.updateDynamicTexture(dynamicTexture);
-//! [1]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qglshaderprogram.cpp b/src/opengl/doc/snippets/code/src_opengl_qglshaderprogram.cpp
deleted file mode 100644
index 04492499e8..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qglshaderprogram.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
-QGLShader shader(QGLShader::Vertex);
-shader.compileSourceCode(code);
-
-QGLShaderProgram program(context);
-program.addShader(shader);
-program.link();
-
-program.bind();
-//! [0]
-
-//! [1]
-program.addShaderFromSourceCode(QGLShader::Vertex,
- "attribute highp vec4 vertex;\n"
- "uniform highp mat4 matrix;\n"
- "void main(void)\n"
- "{\n"
- " gl_Position = matrix * vertex;\n"
- "}");
-program.addShaderFromSourceCode(QGLShader::Fragment,
- "uniform mediump vec4 color;\n"
- "void main(void)\n"
- "{\n"
- " gl_FragColor = color;\n"
- "}");
-program.link();
-program.bind();
-
-int vertexLocation = program.attributeLocation("vertex");
-int matrixLocation = program.uniformLocation("matrix");
-int colorLocation = program.uniformLocation("color");
-//! [1]
-
-//! [2]
-static GLfloat const triangleVertices[] = {
- 60.0f, 10.0f, 0.0f,
- 110.0f, 110.0f, 0.0f,
- 10.0f, 110.0f, 0.0f
-};
-
-QColor color(0, 255, 0, 255);
-
-QMatrix4x4 pmvMatrix;
-pmvMatrix.ortho(rect());
-
-program.enableAttributeArray(vertexLocation);
-program.setAttributeArray(vertexLocation, triangleVertices, 3);
-program.setUniformValue(matrixLocation, pmvMatrix);
-program.setUniformValue(colorLocation, color);
-
-glDrawArrays(GL_TRIANGLES, 0, 3);
-
-program.disableAttributeArray(vertexLocation);
-//! [2]
diff --git a/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp b/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp
deleted file mode 100644
index 461e96e094..0000000000
--- a/src/opengl/doc/snippets/code/src_opengl_qgraphicsshadereffect.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the documentation of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** 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.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//! [0]
- static char const colorizeShaderCode[] =
- "uniform lowp vec4 effectColor;\n"
- "lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n"
- " vec4 src = texture2D(imageTexture, textureCoords);\n"
- " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n"
- " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n"
- " return vec4(colorize.rgb, src.a);\n"
- "}";
-//! [0]
-
-//! [1]
- class ColorizeEffect : public QGraphicsShaderEffect
- {
- Q_OBJECT
- public:
- ColorizeEffect(QObject *parent = 0)
- : QGraphicsShaderEffect(parent), color(Qt::black)
- {
- setPixelShaderFragment(colorizeShaderCode);
- }
-
- QColor effectColor() const { return color; }
- void setEffectColor(const QColor& c)
- {
- color = c;
- setUniformsDirty();
- }
-
- protected:
- void setUniforms(QGLShaderProgram *program)
- {
- program->setUniformValue("effectColor", color);
- }
-
- private:
- QColor color;
- };
-//! [1]
-
-//! [2]
- lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {
- return texture2D(imageTexture, textureCoords);
- }
-//! [2]
diff --git a/src/opengl/doc/src/qtopengl-examples.qdoc b/src/opengl/doc/src/qtopengl-examples.qdoc
index de80c92883..8770d6247e 100644
--- a/src/opengl/doc/src/qtopengl-examples.qdoc
+++ b/src/opengl/doc/src/qtopengl-examples.qdoc
@@ -33,12 +33,11 @@
\image opengl-examples.png
- These examples describe how to use the \l {Qt OpenGL} module. For new code,
- please use the OpenGL classes in the \l {Qt GUI} module.
+ These examples describe how to use the \l {Qt OpenGL} module.
- Qt provides support for integration with OpenGL implementations on all
- platforms, giving developers the opportunity to display hardware accelerated
- 3D graphics alongside a more conventional user interface.
+ Qt provides support for integration with OpenGL implementations, giving
+ developers the opportunity to display hardware accelerated 3D graphics
+ alongside a more conventional user interface.
These examples demonstrate the basic techniques used to take advantage of
OpenGL in Qt applications.
diff --git a/src/opengl/doc/src/qtopengl-module.qdoc b/src/opengl/doc/src/qtopengl-module.qdoc
index 336d37c73f..24df4aec76 100644
--- a/src/opengl/doc/src/qtopengl-module.qdoc
+++ b/src/opengl/doc/src/qtopengl-module.qdoc
@@ -34,8 +34,7 @@
\brief The Qt OpenGL module offers classes that make it easy to
use OpenGL in Qt applications.
- \warning This module should not be used anymore for new code. Please
- use the corresponding OpenGL classes in \l{Qt GUI}.
+ \warning This module should not be used anymore for new code.
OpenGL is a standard API for rendering 3D graphics. OpenGL only
deals with 3D rendering and provides little or no support for GUI
@@ -48,9 +47,6 @@
the United States and other countries.
The Qt OpenGL module makes it easy to use OpenGL in Qt applications.
- It provides an OpenGL widget class that can be used just like any
- other Qt widget, except that it opens an OpenGL display buffer where
- you can use the OpenGL API to render the contents.
To include the definitions of the module's classes, use the
following directive:
@@ -63,11 +59,4 @@
\snippet code/doc_src_qtopengl.pro 1
\endif
-
- The Qt OpenGL module is implemented as a platform-independent Qt/C++
- wrapper around the platform-dependent GLX (version 1.3 or later),
- WGL, or AGL C APIs. Although the basic functionality provided is very
- similar to Mark Kilgard's GLUT library, applications using the Qt
- OpenGL module can take advantage of the whole Qt API for
- non-OpenGL-specific GUI functionality.
*/
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/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/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/opengl.pro b/src/opengl/opengl.pro
index 8b2349ff2f..2a5d7edbee 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -1,57 +1,64 @@
TARGET = QtOpenGL
-QT = core-private gui-private widgets-private
+QT = core-private gui-private
+qtConfig(widgets): QT += widgets widgets-private
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
-msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x63000000
-solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2
-
QMAKE_DOCS = $$PWD/doc/qtopengl.qdocconf
qtConfig(opengl): CONFIG += opengl
qtConfig(opengles2): CONFIG += opengles2
-HEADERS += qgl.h \
- qgl_p.h \
- qglcolormap.h \
- qglfunctions.h \
- qglpixelbuffer.h \
- qglpixelbuffer_p.h \
- qglframebufferobject.h \
- qglframebufferobject_p.h \
- qglpaintdevice_p.h \
- qglbuffer.h \
- qtopenglglobal.h
-
-SOURCES += qgl.cpp \
- qglcolormap.cpp \
- qglfunctions.cpp \
- qglpixelbuffer.cpp \
- qglframebufferobject.cpp \
- qglpaintdevice.cpp \
- qglbuffer.cpp \
-
-HEADERS += qglshaderprogram.h \
- gl2paintengineex/qglgradientcache_p.h \
- gl2paintengineex/qglengineshadermanager_p.h \
- gl2paintengineex/qgl2pexvertexarray_p.h \
- gl2paintengineex/qpaintengineex_opengl2_p.h \
- gl2paintengineex/qglengineshadersource_p.h \
- gl2paintengineex/qglcustomshaderstage_p.h \
- gl2paintengineex/qtextureglyphcache_gl_p.h \
- gl2paintengineex/qglshadercache_p.h
-
-SOURCES += qglshaderprogram.cpp \
- gl2paintengineex/qglgradientcache.cpp \
- gl2paintengineex/qglengineshadermanager.cpp \
- gl2paintengineex/qgl2pexvertexarray.cpp \
- gl2paintengineex/qpaintengineex_opengl2.cpp \
- gl2paintengineex/qglcustomshaderstage.cpp \
- gl2paintengineex/qtextureglyphcache_gl.cpp
-
-qtConfig(graphicseffect) {
- HEADERS += qgraphicsshadereffect_p.h
- SOURCES += qgraphicsshadereffect.cpp
+HEADERS += \
+ qopengl2pexvertexarray_p.h \
+ qopenglcustomshaderstage_p.h \
+ qopengldebug.h \
+ qopenglengineshadermanager_p.h \
+ qopenglengineshadersource_p.h \
+ qopenglgradientcache_p.h \
+ qopenglpaintdevice.h \
+ qopenglpaintdevice_p.h \
+ qopenglpaintengine_p.h \
+ qopenglpixeltransferoptions.h \
+ qopenglshadercache_p.h \
+ qopengltexture.h \
+ qopengltexture_p.h \
+ qopengltexturehelper_p.h \
+ qopengltextureblitter.h \
+ qopengltexturecache_p.h \
+ qopengltextureglyphcache_p.h \
+ qopengltextureuploader_p.h \
+ qopenglwindow.h \
+ qtopenglglobal.h
+
+SOURCES += \
+ qopengl2pexvertexarray.cpp \
+ qopenglcustomshaderstage.cpp \
+ qopenglengineshadermanager.cpp \
+ qopenglgradientcache.cpp \
+ qopenglpaintdevice.cpp \
+ qopenglpaintengine.cpp \
+ qopenglpixeltransferoptions.cpp \
+ qopengltexture.cpp \
+ qopengltexturehelper.cpp \
+ qopengltextureblitter.cpp \
+ qopengltexturecache.cpp \
+ qopengltextureglyphcache.cpp \
+ qopengltextureuploader.cpp \
+ qopenglwindow.cpp \
+ qopengldebug.cpp
+
+!qtConfig(opengles2) {
+ HEADERS += \
+ qopenglqueryhelper_p.h \
+ qopengltimerquery.h
+
+ SOURCES += qopengltimerquery.cpp
+}
+
+qtConfig(widgets) {
+ HEADERS += qopenglwidget.h
+ SOURCES += qopenglwidget.cpp
}
load(qt_module)
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
deleted file mode 100644
index 4108b70094..0000000000
--- a/src/opengl/qgl.cpp
+++ /dev/null
@@ -1,5558 +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 "qapplication.h"
-#include "qplatformdefs.h"
-#include "qgl.h"
-#include <qdebug.h>
-#include <qglfunctions.h>
-
-#include <qdatetime.h>
-
-#include <stdlib.h> // malloc
-
-#include "qpixmap.h"
-#include "qimage.h"
-#include "qgl_p.h"
-
-#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
-
-#include <qpa/qplatformopenglcontext.h>
-
-#include <qglpixelbuffer.h>
-#include <qglframebufferobject.h>
-#include <private/qopenglextensions_p.h>
-
-#include <private/qimage_p.h>
-#include <qpa/qplatformpixmap.h>
-#include <private/qglpixelbuffer_p.h>
-#include <private/qimagepixmapcleanuphooks_p.h>
-#include "qcolormap.h"
-#include "qfile.h"
-#include <qmutex.h>
-
-#include "qsurfaceformat.h"
-#include <private/qapplication_p.h>
-#include <qpa/qplatformopenglcontext.h>
-#include <qpa/qplatformwindow.h>
-
-#ifndef QT_OPENGL_ES_2
-#include <qopenglfunctions_1_1.h>
-#endif
-
-// #define QT_GL_CONTEXT_RESOURCE_DEBUG
-
-QT_BEGIN_NAMESPACE
-
-class QGLDefaultExtensions
-{
-public:
- QGLDefaultExtensions()
- {
- QGLTemporaryContext tempContext;
- Q_ASSERT(QOpenGLContext::currentContext());
- QOpenGLExtensions *ext = qgl_extensions();
- Q_ASSERT(ext);
- extensions = ext->openGLExtensions();
- features = ext->openGLFeatures();
- }
-
- QOpenGLFunctions::OpenGLFeatures features;
- QOpenGLExtensions::OpenGLExtensions extensions;
-};
-
-Q_GLOBAL_STATIC(QGLDefaultExtensions, qtDefaultExtensions)
-
-bool qgl_hasFeature(QOpenGLFunctions::OpenGLFeature feature)
-{
- if (QOpenGLContext::currentContext())
- return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(feature);
- return qtDefaultExtensions()->features & feature;
-}
-
-bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension)
-{
- if (QOpenGLContext::currentContext())
- return qgl_extensions()->hasOpenGLExtension(extension);
- return qtDefaultExtensions()->extensions & extension;
-}
-
-QOpenGLExtensions::OpenGLExtensions extensions;
-
-/*
- Returns the GL extensions for the current QOpenGLContext. If there is no
- current QOpenGLContext, a default context will be created and the extensions
- for that context will be returned instead.
-*/
-QOpenGLExtensions* qgl_extensions()
-{
- if (QOpenGLContext *context = QOpenGLContext::currentContext())
- return static_cast<QOpenGLExtensions *>(context->functions());
-
- Q_ASSERT(false);
- return 0;
-}
-
-QOpenGLFunctions *qgl_functions()
-{
- return qgl_extensions(); // QOpenGLExtensions is just a subclass of QOpenGLFunctions
-}
-
-#ifndef QT_OPENGL_ES_2
-QOpenGLFunctions_1_1 *qgl1_functions()
-{
- QOpenGLFunctions_1_1 *f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_1_1>();
- f->initializeOpenGLFunctions();
- return f;
-}
-#endif
-
-struct QGLThreadContext {
- ~QGLThreadContext() {
- if (context)
- context->doneCurrent();
- }
- QGLContext *context;
-};
-
-Q_GLOBAL_STATIC(QGLFormat, qgl_default_format)
-
-class QGLDefaultOverlayFormat: public QGLFormat
-{
-public:
- inline QGLDefaultOverlayFormat()
- {
- setOption(QGL::FormatOption(0xffffU << 16)); // turn off all options
- setOption(QGL::DirectRendering);
- setPlane(1);
- }
-};
-Q_GLOBAL_STATIC(QGLDefaultOverlayFormat, defaultOverlayFormatInstance)
-
-Q_GLOBAL_STATIC(QGLSignalProxy, theSignalProxy)
-QGLSignalProxy *QGLSignalProxy::instance()
-{
- QGLSignalProxy *proxy = theSignalProxy();
- if (proxy && qApp && proxy->thread() != qApp->thread()) {
- if (proxy->thread() == QThread::currentThread())
- proxy->moveToThread(qApp->thread());
- }
- return proxy;
-}
-
-
-/*!
- \namespace QGL
- \inmodule QtOpenGL
-
- \brief The QGL namespace specifies miscellaneous identifiers used
- in the Qt OpenGL module.
-*/
-
-/*!
- \enum QGL::FormatOption
-
- This enum specifies the format options that can be used to configure an OpenGL
- context. These are set using QGLFormat::setOption().
-
- \value DoubleBuffer Specifies the use of double buffering.
- \value DepthBuffer Enables the use of a depth buffer.
- \value Rgba Specifies that the context should use RGBA as its pixel format.
- \value AlphaChannel Enables the use of an alpha channel.
- \value AccumBuffer Enables the use of an accumulation buffer.
- \value StencilBuffer Enables the use of a stencil buffer.
- \value StereoBuffers Enables the use of a stereo buffers for use with visualization hardware.
- \value DirectRendering Specifies that the context is used for direct rendering to a display.
- \value HasOverlay Enables the use of an overlay.
- \value SampleBuffers Enables the use of sample buffers.
- \value DeprecatedFunctions Enables the use of deprecated functionality for OpenGL 3.x
- contexts. A context with deprecated functionality enabled is
- called a full context in the OpenGL specification.
- \value SingleBuffer Specifies the use of a single buffer, as opposed to double buffers.
- \value NoDepthBuffer Disables the use of a depth buffer.
- \value ColorIndex Specifies that the context should use a color index as its pixel format.
- \value NoAlphaChannel Disables the use of an alpha channel.
- \value NoAccumBuffer Disables the use of an accumulation buffer.
- \value NoStencilBuffer Disables the use of a stencil buffer.
- \value NoStereoBuffers Disables the use of stereo buffers.
- \value IndirectRendering Specifies that the context is used for indirect rendering to a buffer.
- \value NoOverlay Disables the use of an overlay.
- \value NoSampleBuffers Disables the use of sample buffers.
- \value NoDeprecatedFunctions Disables the use of deprecated functionality for OpenGL 3.x
- contexts. A context with deprecated functionality disabled is
- called a forward compatible context in the OpenGL specification.
-*/
-
-/*****************************************************************************
- QGLFormat implementation
- *****************************************************************************/
-
-
-/*!
- \class QGLFormat
- \inmodule QtOpenGL
- \obsolete
-
- \brief The QGLFormat class specifies the display format of an OpenGL
- rendering context.
-
- A display format has several characteristics:
- \list
- \li \l{setDoubleBuffer()}{Double or single buffering.}
- \li \l{setDepth()}{Depth buffer.}
- \li \l{setRgba()}{RGBA or color index mode.}
- \li \l{setAlpha()}{Alpha channel.}
- \li \l{setAccum()}{Accumulation buffer.}
- \li \l{setStencil()}{Stencil buffer.}
- \li \l{setStereo()}{Stereo buffers.}
- \li \l{setDirectRendering()}{Direct rendering.}
- \li \l{setOverlay()}{Presence of an overlay.}
- \li \l{setPlane()}{Plane of an overlay.}
- \li \l{setSampleBuffers()}{Multisample buffers.}
- \endlist
-
- You can also specify preferred bit depths for the color buffer,
- depth buffer, alpha buffer, accumulation buffer and the stencil
- buffer with the functions: setRedBufferSize(), setGreenBufferSize(),
- setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(),
- setAccumBufferSize() and setStencilBufferSize().
-
- Note that even if you specify that you prefer a 32 bit depth
- buffer (e.g. with setDepthBufferSize(32)), the format that is
- chosen may not have a 32 bit depth buffer, even if there is a
- format available with a 32 bit depth buffer. The main reason for
- this is how the system dependant picking algorithms work on the
- different platforms, and some format options may have higher
- precedence than others.
-
- You create and tell a QGLFormat object what rendering options you
- want from an OpenGL rendering context.
-
- OpenGL drivers or accelerated hardware may or may not support
- advanced features such as alpha channel or stereographic viewing.
- If you request some features that the driver/hardware does not
- provide when you create a QGLWidget, you will get a rendering
- context with the nearest subset of features.
-
- There are different ways to define the display characteristics of
- a rendering context. One is to create a QGLFormat and make it the
- default for the entire application:
- \snippet code/src_opengl_qgl.cpp 0
-
- Or you can specify the desired format when creating an object of
- your QGLWidget subclass:
- \snippet code/src_opengl_qgl.cpp 1
-
- After the widget has been created, you can find out which of the
- requested features the system was able to provide:
- \snippet code/src_opengl_qgl.cpp 2
-
- \legalese
- OpenGL is a trademark of Silicon Graphics, Inc. in the
- United States and other countries.
- \endlegalese
-
- \sa QGLContext, QGLWidget
-*/
-
-#ifndef QT_OPENGL_ES
-
-static inline void transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
-{
-#define M(row,col) m[col*4+row]
- out[0] =
- M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
- out[1] =
- M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
- out[2] =
- M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
- out[3] =
- M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
-#undef M
-}
-
-static inline GLint qgluProject(GLdouble objx, GLdouble objy, GLdouble objz,
- const GLdouble model[16], const GLdouble proj[16],
- const GLint viewport[4],
- GLdouble * winx, GLdouble * winy, GLdouble * winz)
-{
- GLdouble in[4], out[4];
-
- in[0] = objx;
- in[1] = objy;
- in[2] = objz;
- in[3] = 1.0;
- transform_point(out, model, in);
- transform_point(in, proj, out);
-
- if (in[3] == 0.0)
- return GL_FALSE;
-
- in[0] /= in[3];
- in[1] /= in[3];
- in[2] /= in[3];
-
- *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
- *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
-
- *winz = (1 + in[2]) / 2;
- return GL_TRUE;
-}
-
-#endif // !QT_OPENGL_ES
-
-/*!
- Constructs a QGLFormat object with the following default settings:
- \list
- \li \l{setDoubleBuffer()}{Double buffer:} Enabled.
- \li \l{setDepth()}{Depth buffer:} Enabled.
- \li \l{setRgba()}{RGBA:} Enabled (i.e., color index disabled).
- \li \l{setAlpha()}{Alpha channel:} Disabled.
- \li \l{setAccum()}{Accumulator buffer:} Disabled.
- \li \l{setStencil()}{Stencil buffer:} Enabled.
- \li \l{setStereo()}{Stereo:} Disabled.
- \li \l{setDirectRendering()}{Direct rendering:} Enabled.
- \li \l{setOverlay()}{Overlay:} Disabled.
- \li \l{setPlane()}{Plane:} 0 (i.e., normal plane).
- \li \l{setSampleBuffers()}{Multisample buffers:} Disabled.
- \endlist
-*/
-
-QGLFormat::QGLFormat()
-{
- d = new QGLFormatPrivate;
-}
-
-
-/*!
- Creates a QGLFormat object that is a copy of the current
- defaultFormat().
-
- If \a options is not 0, the default format is modified by the
- specified format options. The \a options parameter should be
- QGL::FormatOption values OR'ed together.
-
- This constructor makes it easy to specify a certain desired format
- in classes derived from QGLWidget, for example:
- \snippet code/src_opengl_qgl.cpp 3
-
- Note that there are QGL::FormatOption values to turn format settings
- both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer,
- QGL::DirectRendering and QGL::IndirectRendering, etc.
-
- The \a plane parameter defaults to 0 and is the plane which this
- format should be associated with. Not all OpenGL implementations
- supports overlay/underlay rendering planes.
-
- \sa defaultFormat(), setOption(), setPlane()
-*/
-
-QGLFormat::QGLFormat(QGL::FormatOptions options, int plane)
-{
- d = new QGLFormatPrivate;
- QGL::FormatOptions newOpts = options;
- d->opts = defaultFormat().d->opts;
- d->opts |= (newOpts & 0xffff);
- d->opts &= ~(newOpts >> 16);
- d->pln = plane;
-}
-
-/*!
- \internal
-*/
-void QGLFormat::detach()
-{
- if (d->ref.loadRelaxed() != 1) {
- QGLFormatPrivate *newd = new QGLFormatPrivate(d);
- if (!d->ref.deref())
- delete d;
- d = newd;
- }
-}
-
-/*!
- Constructs a copy of \a other.
-*/
-
-QGLFormat::QGLFormat(const QGLFormat &other)
-{
- d = other.d;
- d->ref.ref();
-}
-
-/*!
- Assigns \a other to this object.
-*/
-
-QGLFormat &QGLFormat::operator=(const QGLFormat &other)
-{
- if (d != other.d) {
- other.d->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = other.d;
- }
- return *this;
-}
-
-/*!
- Destroys the QGLFormat.
-*/
-QGLFormat::~QGLFormat()
-{
- if (!d->ref.deref())
- delete d;
-}
-
-/*!
- Returns an OpenGL format for the window format specified by \a format.
-*/
-QGLFormat QGLFormat::fromSurfaceFormat(const QSurfaceFormat &format)
-{
- QGLFormat retFormat;
- if (format.alphaBufferSize() >= 0)
- retFormat.setAlphaBufferSize(format.alphaBufferSize());
- if (format.blueBufferSize() >= 0)
- retFormat.setBlueBufferSize(format.blueBufferSize());
- if (format.greenBufferSize() >= 0)
- retFormat.setGreenBufferSize(format.greenBufferSize());
- if (format.redBufferSize() >= 0)
- retFormat.setRedBufferSize(format.redBufferSize());
- if (format.depthBufferSize() >= 0)
- retFormat.setDepthBufferSize(format.depthBufferSize());
- if (format.samples() > 1) {
- retFormat.setSampleBuffers(true);
- retFormat.setSamples(format.samples());
- }
- if (format.stencilBufferSize() > 0) {
- retFormat.setStencil(true);
- retFormat.setStencilBufferSize(format.stencilBufferSize());
- }
- retFormat.setSwapInterval(format.swapInterval());
- retFormat.setDoubleBuffer(format.swapBehavior() != QSurfaceFormat::SingleBuffer);
- retFormat.setStereo(format.stereo());
- retFormat.setVersion(format.majorVersion(), format.minorVersion());
- retFormat.setProfile(static_cast<QGLFormat::OpenGLContextProfile>(format.profile()));
- return retFormat;
-}
-
-/*!
- Returns a window format for the OpenGL format specified by \a format.
-*/
-QSurfaceFormat QGLFormat::toSurfaceFormat(const QGLFormat &format)
-{
- QSurfaceFormat retFormat;
- if (format.alpha())
- retFormat.setAlphaBufferSize(format.alphaBufferSize() == -1 ? 1 : format.alphaBufferSize());
- if (format.blueBufferSize() >= 0)
- retFormat.setBlueBufferSize(format.blueBufferSize());
- if (format.greenBufferSize() >= 0)
- retFormat.setGreenBufferSize(format.greenBufferSize());
- if (format.redBufferSize() >= 0)
- retFormat.setRedBufferSize(format.redBufferSize());
- if (format.depth())
- retFormat.setDepthBufferSize(format.depthBufferSize() == -1 ? 1 : format.depthBufferSize());
- retFormat.setSwapBehavior(format.doubleBuffer() ? QSurfaceFormat::DoubleBuffer : QSurfaceFormat::SingleBuffer);
- if (format.sampleBuffers())
- retFormat.setSamples(format.samples() == -1 ? 4 : format.samples());
- if (format.stencil())
- retFormat.setStencilBufferSize(format.stencilBufferSize() == -1 ? 1 : format.stencilBufferSize());
- retFormat.setSwapInterval(format.swapInterval());
- retFormat.setStereo(format.stereo());
- retFormat.setMajorVersion(format.majorVersion());
- retFormat.setMinorVersion(format.minorVersion());
- retFormat.setProfile(static_cast<QSurfaceFormat::OpenGLContextProfile>(format.profile()));
- // QGLFormat has no way to set DeprecatedFunctions, that is, to tell that forward
- // compatibility should not be requested. Some drivers fail to ignore the fwdcompat
- // bit with compatibility profiles so make sure it is not set.
- if (format.profile() == QGLFormat::CompatibilityProfile)
- retFormat.setOption(QSurfaceFormat::DeprecatedFunctions);
- return retFormat;
-}
-
-void QGLContextPrivate::setupSharing() {
- Q_Q(QGLContext);
- QOpenGLContext *sharedContext = guiGlContext->shareContext();
- if (sharedContext) {
- QGLContext *actualSharedContext = QGLContext::fromOpenGLContext(sharedContext);
- sharing = true;
- QGLContextGroup::addShare(q, actualSharedContext);
- }
-}
-
-void QGLContextPrivate::refreshCurrentFbo()
-{
- QOpenGLContextPrivate *guiGlContextPrivate =
- guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
-
- // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value
- if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) {
- GLint current;
- QOpenGLFunctions *funcs = qgl_functions();
- funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &current);
-
- current_fbo = current;
-
- guiGlContextPrivate->qgl_current_fbo_invalid = false;
- }
-}
-
-void QGLContextPrivate::setCurrentFbo(GLuint fbo)
-{
- current_fbo = fbo;
-
- QOpenGLContextPrivate *guiGlContextPrivate =
- guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
-
- if (guiGlContextPrivate)
- guiGlContextPrivate->qgl_current_fbo_invalid = false;
-}
-
-
-/*!
- \fn bool QGLFormat::doubleBuffer() const
-
- Returns \c true if double buffering is enabled; otherwise returns
- false. Double buffering is enabled by default.
-
- \sa setDoubleBuffer()
-*/
-
-/*!
- If \a enable is true sets double buffering; otherwise sets single
- buffering.
-
- Double buffering is enabled by default.
-
- Double buffering is a technique where graphics are rendered on an
- off-screen buffer and not directly to the screen. When the drawing
- has been completed, the program calls a swapBuffers() function to
- exchange the screen contents with the buffer. The result is
- flicker-free drawing and often better performance.
-
- Note that single buffered contexts are currently not supported
- with EGL.
-
- \sa doubleBuffer(), QGLContext::swapBuffers(),
- QGLWidget::swapBuffers()
-*/
-
-void QGLFormat::setDoubleBuffer(bool enable)
-{
- setOption(enable ? QGL::DoubleBuffer : QGL::SingleBuffer);
-}
-
-
-/*!
- \fn bool QGLFormat::depth() const
-
- Returns \c true if the depth buffer is enabled; otherwise returns
- false. The depth buffer is enabled by default.
-
- \sa setDepth(), setDepthBufferSize()
-*/
-
-/*!
- If \a enable is true enables the depth buffer; otherwise disables
- the depth buffer.
-
- The depth buffer is enabled by default.
-
- The purpose of a depth buffer (or Z-buffering) is to remove hidden
- surfaces. Pixels are assigned Z values based on the distance to
- the viewer. A pixel with a high Z value is closer to the viewer
- than a pixel with a low Z value. This information is used to
- decide whether to draw a pixel or not.
-
- \sa depth(), setDepthBufferSize()
-*/
-
-void QGLFormat::setDepth(bool enable)
-{
- setOption(enable ? QGL::DepthBuffer : QGL::NoDepthBuffer);
-}
-
-
-/*!
- \fn bool QGLFormat::rgba() const
-
- Returns \c true if RGBA color mode is set. Returns \c false if color
- index mode is set. The default color mode is RGBA.
-
- \sa setRgba()
-*/
-
-/*!
- If \a enable is true sets RGBA mode. If \a enable is false sets
- color index mode.
-
- The default color mode is RGBA.
-
- RGBA is the preferred mode for most OpenGL applications. In RGBA
- color mode you specify colors as red + green + blue + alpha
- quadruplets.
-
- In color index mode you specify an index into a color lookup
- table.
-
- \sa rgba()
-*/
-
-void QGLFormat::setRgba(bool enable)
-{
- setOption(enable ? QGL::Rgba : QGL::ColorIndex);
-}
-
-
-/*!
- \fn bool QGLFormat::alpha() const
-
- Returns \c true if the alpha buffer in the framebuffer is enabled;
- otherwise returns \c false. The alpha buffer is disabled by default.
-
- \sa setAlpha(), setAlphaBufferSize()
-*/
-
-/*!
- If \a enable is true enables the alpha buffer; otherwise disables
- the alpha buffer.
-
- The alpha buffer is disabled by default.
-
- The alpha buffer is typically used for implementing transparency
- or translucency. The A in RGBA specifies the transparency of a
- pixel.
-
- \sa alpha(), setAlphaBufferSize()
-*/
-
-void QGLFormat::setAlpha(bool enable)
-{
- setOption(enable ? QGL::AlphaChannel : QGL::NoAlphaChannel);
-}
-
-
-/*!
- \fn bool QGLFormat::accum() const
-
- Returns \c true if the accumulation buffer is enabled; otherwise
- returns \c false. The accumulation buffer is disabled by default.
-
- \sa setAccum(), setAccumBufferSize()
-*/
-
-/*!
- If \a enable is true enables the accumulation buffer; otherwise
- disables the accumulation buffer.
-
- The accumulation buffer is disabled by default.
-
- The accumulation buffer is used to create blur effects and
- multiple exposures.
-
- \sa accum(), setAccumBufferSize()
-*/
-
-void QGLFormat::setAccum(bool enable)
-{
- setOption(enable ? QGL::AccumBuffer : QGL::NoAccumBuffer);
-}
-
-
-/*!
- \fn bool QGLFormat::stencil() const
-
- Returns \c true if the stencil buffer is enabled; otherwise returns
- false. The stencil buffer is enabled by default.
-
- \sa setStencil(), setStencilBufferSize()
-*/
-
-/*!
- If \a enable is true enables the stencil buffer; otherwise
- disables the stencil buffer.
-
- The stencil buffer is enabled by default.
-
- The stencil buffer masks certain parts of the drawing area so that
- masked parts are not drawn on.
-
- \sa stencil(), setStencilBufferSize()
-*/
-
-void QGLFormat::setStencil(bool enable)
-{
- setOption(enable ? QGL::StencilBuffer: QGL::NoStencilBuffer);
-}
-
-
-/*!
- \fn bool QGLFormat::stereo() const
-
- Returns \c true if stereo buffering is enabled; otherwise returns
- false. Stereo buffering is disabled by default.
-
- \sa setStereo()
-*/
-
-/*!
- If \a enable is true enables stereo buffering; otherwise disables
- stereo buffering.
-
- Stereo buffering is disabled by default.
-
- Stereo buffering provides extra color buffers to generate left-eye
- and right-eye images.
-
- \sa stereo()
-*/
-
-void QGLFormat::setStereo(bool enable)
-{
- setOption(enable ? QGL::StereoBuffers : QGL::NoStereoBuffers);
-}
-
-
-/*!
- \fn bool QGLFormat::directRendering() const
-
- Returns \c true if direct rendering is enabled; otherwise returns
- false.
-
- Direct rendering is enabled by default.
-
- \sa setDirectRendering()
-*/
-
-/*!
- If \a enable is true enables direct rendering; otherwise disables
- direct rendering.
-
- Direct rendering is enabled by default.
-
- Enabling this option will make OpenGL bypass the underlying window
- system and render directly from hardware to the screen, if this is
- supported by the system.
-
- \sa directRendering()
-*/
-
-void QGLFormat::setDirectRendering(bool enable)
-{
- setOption(enable ? QGL::DirectRendering : QGL::IndirectRendering);
-}
-
-/*!
- \fn bool QGLFormat::sampleBuffers() const
-
- Returns \c true if multisample buffer support is enabled; otherwise
- returns \c false.
-
- The multisample buffer is disabled by default.
-
- \sa setSampleBuffers()
-*/
-
-/*!
- If \a enable is true, a GL context with multisample buffer support
- is picked; otherwise ignored.
-
- \sa sampleBuffers(), setSamples(), samples()
-*/
-void QGLFormat::setSampleBuffers(bool enable)
-{
- setOption(enable ? QGL::SampleBuffers : QGL::NoSampleBuffers);
-}
-
-/*!
- Returns the number of samples per pixel when multisampling is
- enabled. By default, the highest number of samples that is
- available is used.
-
- \sa setSampleBuffers(), sampleBuffers(), setSamples()
-*/
-int QGLFormat::samples() const
-{
- return d->numSamples;
-}
-
-/*!
- Set the preferred number of samples per pixel when multisampling
- is enabled to \a numSamples. By default, the highest number of
- samples available is used.
-
- \sa setSampleBuffers(), sampleBuffers(), samples()
-*/
-void QGLFormat::setSamples(int numSamples)
-{
- detach();
- if (numSamples < 0) {
- qWarning("QGLFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples);
- return;
- }
- d->numSamples = numSamples;
- setSampleBuffers(numSamples > 0);
-}
-
-/*!
- \since 4.2
-
- Set the preferred swap interval. This can be used to sync the GL
- drawing into a system window to the vertical refresh of the screen.
- Setting an \a interval value of 0 will turn the vertical refresh syncing
- off, any value higher than 0 will turn the vertical syncing on.
-
- Under Windows and under X11, where the \c{WGL_EXT_swap_control}
- and \c{GLX_SGI_video_sync} extensions are used, the \a interval
- parameter can be used to set the minimum number of video frames
- that are displayed before a buffer swap will occur. In effect,
- setting the \a interval to 10, means there will be 10 vertical
- retraces between every buffer swap.
-
- Under Windows the \c{WGL_EXT_swap_control} extension has to be present,
- and under X11 the \c{GLX_SGI_video_sync} extension has to be present.
-*/
-void QGLFormat::setSwapInterval(int interval)
-{
- detach();
- d->swapInterval = interval;
-}
-
-/*!
- \since 4.2
-
- Returns the currently set swap interval. -1 is returned if setting
- the swap interval isn't supported in the system GL implementation.
-*/
-int QGLFormat::swapInterval() const
-{
- return d->swapInterval;
-}
-
-/*!
- \fn bool QGLFormat::hasOverlay() const
-
- Returns \c true if overlay plane is enabled; otherwise returns \c false.
-
- Overlay is disabled by default.
-
- \sa setOverlay()
-*/
-
-/*!
- If \a enable is true enables an overlay plane; otherwise disables
- the overlay plane.
-
- Enabling the overlay plane will cause QGLWidget to create an
- additional context in an overlay plane. See the QGLWidget
- documentation for further information.
-
- \sa hasOverlay()
-*/
-
-void QGLFormat::setOverlay(bool enable)
-{
- setOption(enable ? QGL::HasOverlay : QGL::NoOverlay);
-}
-
-/*!
- Returns the plane of this format. The default for normal formats
- is 0, which means the normal plane. The default for overlay
- formats is 1, which is the first overlay plane.
-
- \sa setPlane(), defaultOverlayFormat()
-*/
-int QGLFormat::plane() const
-{
- return d->pln;
-}
-
-/*!
- Sets the requested plane to \a plane. 0 is the normal plane, 1 is
- the first overlay plane, 2 is the second overlay plane, etc.; -1,
- -2, etc. are underlay planes.
-
- Note that in contrast to other format specifications, the plane
- specifications will be matched exactly. This means that if you
- specify a plane that the underlying OpenGL system cannot provide,
- an \l{QGLWidget::isValid()}{invalid} QGLWidget will be
- created.
-
- \sa plane()
-*/
-void QGLFormat::setPlane(int plane)
-{
- detach();
- d->pln = plane;
-}
-
-/*!
- Sets the format option to \a opt.
-
- \sa testOption()
-*/
-
-void QGLFormat::setOption(QGL::FormatOptions opt)
-{
- detach();
- if (opt & 0xffff)
- d->opts |= opt;
- else
- d->opts &= ~(opt >> 16);
-}
-
-
-
-/*!
- Returns \c true if format option \a opt is set; otherwise returns \c false.
-
- \sa setOption()
-*/
-
-bool QGLFormat::testOption(QGL::FormatOptions opt) const
-{
- if (opt & 0xffff)
- return (d->opts & opt) != 0;
- else
- return (d->opts & (opt >> 16)) == 0;
-}
-
-/*!
- Set the minimum depth buffer size to \a size.
-
- \sa depthBufferSize(), setDepth(), depth()
-*/
-void QGLFormat::setDepthBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size);
- return;
- }
- d->depthSize = size;
- setDepth(size > 0);
-}
-
-/*!
- Returns the depth buffer size.
-
- \sa depth(), setDepth(), setDepthBufferSize()
-*/
-int QGLFormat::depthBufferSize() const
-{
- return d->depthSize;
-}
-
-/*!
- \since 4.2
-
- Set the preferred red buffer size to \a size.
-
- \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
-*/
-void QGLFormat::setRedBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setRedBufferSize: Cannot set negative red buffer size %d", size);
- return;
- }
- d->redSize = size;
-}
-
-/*!
- \since 4.2
-
- Returns the red buffer size.
-
- \sa setRedBufferSize()
-*/
-int QGLFormat::redBufferSize() const
-{
- return d->redSize;
-}
-
-/*!
- \since 4.2
-
- Set the preferred green buffer size to \a size.
-
- \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize()
-*/
-void QGLFormat::setGreenBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size);
- return;
- }
- d->greenSize = size;
-}
-
-/*!
- \since 4.2
-
- Returns the green buffer size.
-
- \sa setGreenBufferSize()
-*/
-int QGLFormat::greenBufferSize() const
-{
- return d->greenSize;
-}
-
-/*!
- \since 4.2
-
- Set the preferred blue buffer size to \a size.
-
- \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize()
-*/
-void QGLFormat::setBlueBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size);
- return;
- }
- d->blueSize = size;
-}
-
-/*!
- \since 4.2
-
- Returns the blue buffer size.
-
- \sa setBlueBufferSize()
-*/
-int QGLFormat::blueBufferSize() const
-{
- return d->blueSize;
-}
-
-/*!
- Set the preferred alpha buffer size to \a size.
- This function implicitly enables the alpha channel.
-
- \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize()
-*/
-void QGLFormat::setAlphaBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size);
- return;
- }
- d->alphaSize = size;
- setAlpha(size > 0);
-}
-
-/*!
- Returns the alpha buffer size.
-
- \sa alpha(), setAlpha(), setAlphaBufferSize()
-*/
-int QGLFormat::alphaBufferSize() const
-{
- return d->alphaSize;
-}
-
-/*!
- Set the preferred accumulation buffer size, where \a size is the
- bit depth for each RGBA component.
-
- \sa accum(), setAccum(), accumBufferSize()
-*/
-void QGLFormat::setAccumBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size);
- return;
- }
- d->accumSize = size;
- setAccum(size > 0);
-}
-
-/*!
- Returns the accumulation buffer size.
-
- \sa setAccumBufferSize(), accum(), setAccum()
-*/
-int QGLFormat::accumBufferSize() const
-{
- return d->accumSize;
-}
-
-/*!
- Set the preferred stencil buffer size to \a size.
-
- \sa stencilBufferSize(), setStencil(), stencil()
-*/
-void QGLFormat::setStencilBufferSize(int size)
-{
- detach();
- if (size < 0) {
- qWarning("QGLFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size);
- return;
- }
- d->stencilSize = size;
- setStencil(size > 0);
-}
-
-/*!
- Returns the stencil buffer size.
-
- \sa stencil(), setStencil(), setStencilBufferSize()
-*/
-int QGLFormat::stencilBufferSize() const
-{
- return d->stencilSize;
-}
-
-/*!
- \since 4.7
-
- Set the OpenGL version to the \a major and \a minor numbers. If a
- context compatible with the requested OpenGL version cannot be
- created, a context compatible with version 1.x is created instead.
-
- \sa majorVersion(), minorVersion()
-*/
-void QGLFormat::setVersion(int major, int minor)
-{
- if (major < 1 || minor < 0) {
- qWarning("QGLFormat::setVersion: Cannot set zero or negative version number %d.%d", major, minor);
- return;
- }
- detach();
- d->majorVersion = major;
- d->minorVersion = minor;
-}
-
-/*!
- \since 4.7
-
- Returns the OpenGL major version.
-
- \sa setVersion(), minorVersion()
-*/
-int QGLFormat::majorVersion() const
-{
- return d->majorVersion;
-}
-
-/*!
- \since 4.7
-
- Returns the OpenGL minor version.
-
- \sa setVersion(), majorVersion()
-*/
-int QGLFormat::minorVersion() const
-{
- return d->minorVersion;
-}
-
-/*!
- \enum QGLFormat::OpenGLContextProfile
- \since 4.7
-
- This enum describes the OpenGL context profiles that can be
- specified for contexts implementing OpenGL version 3.2 or
- higher. These profiles are different from OpenGL ES profiles.
-
- \value NoProfile OpenGL version is lower than 3.2.
- \value CoreProfile Functionality deprecated in OpenGL version 3.0 is not available.
- \value CompatibilityProfile Functionality from earlier OpenGL versions is available.
-*/
-
-/*!
- \since 4.7
-
- Set the OpenGL context profile to \a profile. The \a profile is
- ignored if the requested OpenGL version is less than 3.2.
-
- \sa profile()
-*/
-void QGLFormat::setProfile(OpenGLContextProfile profile)
-{
- detach();
- d->profile = profile;
-}
-
-/*!
- \since 4.7
-
- Returns the OpenGL context profile.
-
- \sa setProfile()
-*/
-QGLFormat::OpenGLContextProfile QGLFormat::profile() const
-{
- return d->profile;
-}
-
-
-/*!
- \fn bool QGLFormat::hasOpenGL()
-
- Returns \c true if the window system has any OpenGL support;
- otherwise returns \c false.
-
- \warning This function must not be called until the QApplication
- object has been created.
-*/
-bool QGLFormat::hasOpenGL()
-{
- return QApplicationPrivate::platformIntegration()
- ->hasCapability(QPlatformIntegration::OpenGL);
-}
-
-/*!
- \fn bool QGLFormat::hasOpenGLOverlays()
-
- Returns \c true if the window system supports OpenGL overlays;
- otherwise returns \c false.
-
- \warning This function must not be called until the QApplication
- object has been created.
-*/
-bool QGLFormat::hasOpenGLOverlays()
-{
- return false;
-}
-
-QGLFormat::OpenGLVersionFlags Q_AUTOTEST_EXPORT qOpenGLVersionFlagsFromString(const QString &versionString)
-{
- QGLFormat::OpenGLVersionFlags versionFlags = QGLFormat::OpenGL_Version_None;
-
- if (versionString.startsWith(QLatin1String("OpenGL ES"))) {
- const auto parts = versionString.splitRef(QLatin1Char(' '));
- if (parts.size() >= 3) {
- if (parts[2].startsWith(QLatin1String("1."))) {
- if (parts[1].endsWith(QLatin1String("-CM"))) {
- versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_0 |
- QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
- if (parts[2].startsWith(QLatin1String("1.1")))
- versionFlags |= QGLFormat::OpenGL_ES_Common_Version_1_1 |
- QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
- } else {
- // Not -CM, must be CL, CommonLite
- versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_0;
- if (parts[2].startsWith(QLatin1String("1.1")))
- versionFlags |= QGLFormat::OpenGL_ES_CommonLite_Version_1_1;
- }
- } else {
- // OpenGL ES version 2.0 or higher
- versionFlags |= QGLFormat::OpenGL_ES_Version_2_0;
- }
- } else {
- // if < 3 parts to the name, it is an unrecognised OpenGL ES
- qWarning("Unrecognised OpenGL ES version");
- }
- } else {
- // not ES, regular OpenGL, the version numbers are first in the string
- if (versionString.startsWith(QLatin1String("1."))) {
- switch (versionString[2].toLatin1()) {
- case '5':
- versionFlags |= QGLFormat::OpenGL_Version_1_5;
- Q_FALLTHROUGH();
- case '4':
- versionFlags |= QGLFormat::OpenGL_Version_1_4;
- Q_FALLTHROUGH();
- case '3':
- versionFlags |= QGLFormat::OpenGL_Version_1_3;
- Q_FALLTHROUGH();
- case '2':
- versionFlags |= QGLFormat::OpenGL_Version_1_2;
- Q_FALLTHROUGH();
- case '1':
- versionFlags |= QGLFormat::OpenGL_Version_1_1;
- Q_FALLTHROUGH();
- default:
- break;
- }
- } else if (versionString.startsWith(QLatin1String("2."))) {
- versionFlags |= QGLFormat::OpenGL_Version_1_1 |
- QGLFormat::OpenGL_Version_1_2 |
- QGLFormat::OpenGL_Version_1_3 |
- QGLFormat::OpenGL_Version_1_4 |
- QGLFormat::OpenGL_Version_1_5 |
- QGLFormat::OpenGL_Version_2_0;
- if (versionString[2].toLatin1() == '1')
- versionFlags |= QGLFormat::OpenGL_Version_2_1;
- } else if (versionString.startsWith(QLatin1String("3."))) {
- versionFlags |= QGLFormat::OpenGL_Version_1_1 |
- QGLFormat::OpenGL_Version_1_2 |
- QGLFormat::OpenGL_Version_1_3 |
- QGLFormat::OpenGL_Version_1_4 |
- QGLFormat::OpenGL_Version_1_5 |
- QGLFormat::OpenGL_Version_2_0 |
- QGLFormat::OpenGL_Version_2_1 |
- QGLFormat::OpenGL_Version_3_0;
- switch (versionString[2].toLatin1()) {
- case '3':
- versionFlags |= QGLFormat::OpenGL_Version_3_3;
- Q_FALLTHROUGH();
- case '2':
- versionFlags |= QGLFormat::OpenGL_Version_3_2;
- Q_FALLTHROUGH();
- case '1':
- versionFlags |= QGLFormat::OpenGL_Version_3_1;
- Q_FALLTHROUGH();
- case '0':
- break;
- default:
- versionFlags |= QGLFormat::OpenGL_Version_3_1 |
- QGLFormat::OpenGL_Version_3_2 |
- QGLFormat::OpenGL_Version_3_3;
- break;
- }
- } else if (versionString.startsWith(QLatin1String("4."))) {
- versionFlags |= QGLFormat::OpenGL_Version_1_1 |
- QGLFormat::OpenGL_Version_1_2 |
- QGLFormat::OpenGL_Version_1_3 |
- QGLFormat::OpenGL_Version_1_4 |
- QGLFormat::OpenGL_Version_1_5 |
- QGLFormat::OpenGL_Version_2_0 |
- QGLFormat::OpenGL_Version_2_1 |
- QGLFormat::OpenGL_Version_3_0 |
- QGLFormat::OpenGL_Version_3_1 |
- QGLFormat::OpenGL_Version_3_2 |
- QGLFormat::OpenGL_Version_3_3 |
- QGLFormat::OpenGL_Version_4_0;
- switch (versionString[2].toLatin1()) {
- case '3':
- versionFlags |= QGLFormat::OpenGL_Version_4_3;
- Q_FALLTHROUGH();
- case '2':
- versionFlags |= QGLFormat::OpenGL_Version_4_2;
- Q_FALLTHROUGH();
- case '1':
- versionFlags |= QGLFormat::OpenGL_Version_4_1;
- Q_FALLTHROUGH();
- case '0':
- break;
- default:
- versionFlags |= QGLFormat::OpenGL_Version_4_1 |
- QGLFormat::OpenGL_Version_4_2 |
- QGLFormat::OpenGL_Version_4_3;
- break;
- }
- } else {
- versionFlags |= QGLFormat::OpenGL_Version_1_1 |
- QGLFormat::OpenGL_Version_1_2 |
- QGLFormat::OpenGL_Version_1_3 |
- QGLFormat::OpenGL_Version_1_4 |
- QGLFormat::OpenGL_Version_1_5 |
- QGLFormat::OpenGL_Version_2_0 |
- QGLFormat::OpenGL_Version_2_1 |
- QGLFormat::OpenGL_Version_3_0 |
- QGLFormat::OpenGL_Version_3_1 |
- QGLFormat::OpenGL_Version_3_2 |
- QGLFormat::OpenGL_Version_3_3 |
- QGLFormat::OpenGL_Version_4_0 |
- QGLFormat::OpenGL_Version_4_1 |
- QGLFormat::OpenGL_Version_4_2 |
- QGLFormat::OpenGL_Version_4_3;
- }
- }
- return versionFlags;
-}
-
-/*!
- \enum QGLFormat::OpenGLVersionFlag
- \since 4.2
-
- This enum describes the various OpenGL versions that are
- recognized by Qt. Use the QGLFormat::openGLVersionFlags() function
- to identify which versions that are supported at runtime.
-
- \value OpenGL_Version_None If no OpenGL is present or if no OpenGL context is current.
-
- \value OpenGL_Version_1_1 OpenGL version 1.1 or higher is present.
-
- \value OpenGL_Version_1_2 OpenGL version 1.2 or higher is present.
-
- \value OpenGL_Version_1_3 OpenGL version 1.3 or higher is present.
-
- \value OpenGL_Version_1_4 OpenGL version 1.4 or higher is present.
-
- \value OpenGL_Version_1_5 OpenGL version 1.5 or higher is present.
-
- \value OpenGL_Version_2_0 OpenGL version 2.0 or higher is present.
- Note that version 2.0 supports all the functionality of version 1.5.
-
- \value OpenGL_Version_2_1 OpenGL version 2.1 or higher is present.
-
- \value OpenGL_Version_3_0 OpenGL version 3.0 or higher is present.
-
- \value OpenGL_Version_3_1 OpenGL version 3.1 or higher is present.
- Note that OpenGL version 3.1 or higher does not necessarily support all the features of
- version 3.0 and lower.
-
- \value OpenGL_Version_3_2 OpenGL version 3.2 or higher is present.
-
- \value OpenGL_Version_3_3 OpenGL version 3.3 or higher is present.
-
- \value OpenGL_Version_4_0 OpenGL version 4.0 or higher is present.
-
- \value OpenGL_Version_4_1 OpenGL version 4.1 or higher is present.
-
- \value OpenGL_Version_4_2 OpenGL version 4.2 or higher is present.
-
- \value OpenGL_Version_4_3 OpenGL version 4.3 or higher is present.
-
- \value OpenGL_ES_CommonLite_Version_1_0 OpenGL ES version 1.0 Common Lite or higher is present.
-
- \value OpenGL_ES_Common_Version_1_0 OpenGL ES version 1.0 Common or higher is present.
- The Common profile supports all the features of Common Lite.
-
- \value OpenGL_ES_CommonLite_Version_1_1 OpenGL ES version 1.1 Common Lite or higher is present.
-
- \value OpenGL_ES_Common_Version_1_1 OpenGL ES version 1.1 Common or higher is present.
- The Common profile supports all the features of Common Lite.
-
- \value OpenGL_ES_Version_2_0 OpenGL ES version 2.0 or higher is present.
- Note that OpenGL ES version 2.0 does not support all the features of OpenGL ES 1.x.
- So if OpenGL_ES_Version_2_0 is returned, none of the ES 1.x flags are returned.
-
- See also \l{http://www.opengl.org} for more information about the different
- revisions of OpenGL.
-
- \sa openGLVersionFlags()
-*/
-
-/*!
- \since 4.2
-
- Identifies, at runtime, which OpenGL versions that are supported
- by the current platform.
-
- Note that if OpenGL version 1.5 is supported, its predecessors
- (i.e., version 1.4 and lower) are also supported. To identify the
- support of a particular feature, like multi texturing, test for
- the version in which the feature was first introduced (i.e.,
- version 1.3 in the case of multi texturing) to adapt to the largest
- possible group of runtime platforms.
-
- This function needs a valid current OpenGL context to work;
- otherwise it will return OpenGL_Version_None.
-
- \sa hasOpenGL(), hasOpenGLOverlays()
-*/
-QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags()
-{
- static bool cachedDefault = false;
- static OpenGLVersionFlags defaultVersionFlags = OpenGL_Version_None;
- QGLContext *currentCtx = const_cast<QGLContext *>(QGLContext::currentContext());
- QGLTemporaryContext *tmpContext = 0;
-
- if (currentCtx && currentCtx->d_func()->version_flags_cached)
- return currentCtx->d_func()->version_flags;
-
- if (!currentCtx) {
- if (cachedDefault) {
- return defaultVersionFlags;
- } else {
- if (!hasOpenGL())
- return defaultVersionFlags;
- tmpContext = new QGLTemporaryContext;
- cachedDefault = true;
- }
- }
-
- QString versionString(QLatin1String(reinterpret_cast<const char*>(qgl_functions()->glGetString(GL_VERSION))));
- OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString);
- if (currentCtx) {
- currentCtx->d_func()->version_flags_cached = true;
- currentCtx->d_func()->version_flags = versionFlags;
- }
- if (tmpContext) {
- defaultVersionFlags = versionFlags;
- delete tmpContext;
- }
-
- return versionFlags;
-}
-
-
-/*!
- Returns the default QGLFormat for the application. All QGLWidget
- objects that are created use this format unless another format is
- specified, e.g. when they are constructed.
-
- If no special default format has been set using
- setDefaultFormat(), the default format is the same as that created
- with QGLFormat().
-
- \sa setDefaultFormat()
-*/
-
-QGLFormat QGLFormat::defaultFormat()
-{
- return *qgl_default_format();
-}
-
-/*!
- Sets a new default QGLFormat for the application to \a f. For
- example, to set single buffering as the default instead of double
- buffering, your main() might contain code like this:
- \snippet code/src_opengl_qgl.cpp 4
-
- \sa defaultFormat()
-*/
-
-void QGLFormat::setDefaultFormat(const QGLFormat &f)
-{
- *qgl_default_format() = f;
-}
-
-
-/*!
- Returns the default QGLFormat for overlay contexts.
-
- The default overlay format is:
- \list
- \li \l{setDoubleBuffer()}{Double buffer:} Disabled.
- \li \l{setDepth()}{Depth buffer:} Disabled.
- \li \l{setRgba()}{RGBA:} Disabled (i.e., color index enabled).
- \li \l{setAlpha()}{Alpha channel:} Disabled.
- \li \l{setAccum()}{Accumulator buffer:} Disabled.
- \li \l{setStencil()}{Stencil buffer:} Disabled.
- \li \l{setStereo()}{Stereo:} Disabled.
- \li \l{setDirectRendering()}{Direct rendering:} Enabled.
- \li \l{setOverlay()}{Overlay:} Disabled.
- \li \l{setSampleBuffers()}{Multisample buffers:} Disabled.
- \li \l{setPlane()}{Plane:} 1 (i.e., first overlay plane).
- \endlist
-
- \sa setDefaultFormat()
-*/
-
-QGLFormat QGLFormat::defaultOverlayFormat()
-{
- return *defaultOverlayFormatInstance();
-}
-
-/*!
- Sets a new default QGLFormat for overlay contexts to \a f. This
- format is used whenever a QGLWidget is created with a format that
- hasOverlay() enabled.
-
- For example, to get a double buffered overlay context (if
- available), use code like this:
-
- \snippet code/src_opengl_qgl.cpp 5
-
- As usual, you can find out after widget creation whether the
- underlying OpenGL system was able to provide the requested
- specification:
-
- \snippet code/src_opengl_qgl.cpp 6
-
- \sa defaultOverlayFormat()
-*/
-
-void QGLFormat::setDefaultOverlayFormat(const QGLFormat &f)
-{
- QGLFormat *defaultFormat = defaultOverlayFormatInstance();
- *defaultFormat = f;
- // Make sure the user doesn't request that the overlays themselves
- // have overlays, since it is unlikely that the system supports
- // infinitely many planes...
- defaultFormat->setOverlay(false);
-}
-
-
-/*!
- Returns \c true if all the options of the two QGLFormat objects
- \a a and \a b are equal; otherwise returns \c false.
-
- \relates QGLFormat
-*/
-
-bool operator==(const QGLFormat& a, const QGLFormat& b)
-{
- return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
- && a.d->pln == b.d->pln
- && a.d->alphaSize == b.d->alphaSize
- && a.d->accumSize == b.d->accumSize
- && a.d->stencilSize == b.d->stencilSize
- && a.d->depthSize == b.d->depthSize
- && a.d->redSize == b.d->redSize
- && a.d->greenSize == b.d->greenSize
- && a.d->blueSize == b.d->blueSize
- && a.d->numSamples == b.d->numSamples
- && a.d->swapInterval == b.d->swapInterval
- && a.d->majorVersion == b.d->majorVersion
- && a.d->minorVersion == b.d->minorVersion
- && a.d->profile == b.d->profile);
-}
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug dbg, const QGLFormat &f)
-{
- const QGLFormatPrivate * const d = f.d;
-
- QDebugStateSaver saver(dbg);
- dbg.nospace() << "QGLFormat("
- << "options " << d->opts
- << ", plane " << d->pln
- << ", depthBufferSize " << d->depthSize
- << ", accumBufferSize " << d->accumSize
- << ", stencilBufferSize " << d->stencilSize
- << ", redBufferSize " << d->redSize
- << ", greenBufferSize " << d->greenSize
- << ", blueBufferSize " << d->blueSize
- << ", alphaBufferSize " << d->alphaSize
- << ", samples " << d->numSamples
- << ", swapInterval " << d->swapInterval
- << ", majorVersion " << d->majorVersion
- << ", minorVersion " << d->minorVersion
- << ", profile " << d->profile
- << ')';
-
- return dbg;
-}
-#endif
-
-
-/*!
- Returns \c false if all the options of the two QGLFormat objects
- \a a and \a b are equal; otherwise returns \c true.
-
- \relates QGLFormat
-*/
-
-bool operator!=(const QGLFormat& a, const QGLFormat& b)
-{
- return !(a == b);
-}
-
-struct QGLContextGroupList {
- void append(QGLContextGroup *group) {
- QMutexLocker locker(&m_mutex);
- m_list.append(group);
- }
-
- void remove(QGLContextGroup *group) {
- QMutexLocker locker(&m_mutex);
- m_list.removeOne(group);
- }
-
- QList<QGLContextGroup *> m_list;
- QRecursiveMutex m_mutex;
-};
-
-Q_GLOBAL_STATIC(QGLContextGroupList, qt_context_groups)
-
-/*****************************************************************************
- QGLContext implementation
- *****************************************************************************/
-
-QGLContextGroup::QGLContextGroup(const QGLContext *context)
- : m_context(context), m_refs(1)
-{
- qt_context_groups()->append(this);
-}
-
-QGLContextGroup::~QGLContextGroup()
-{
- qt_context_groups()->remove(this);
-}
-
-const QGLContext *qt_gl_transfer_context(const QGLContext *ctx)
-{
- if (!ctx)
- return 0;
- QList<const QGLContext *> shares
- (QGLContextPrivate::contextGroup(ctx)->shares());
- if (shares.size() >= 2)
- return (ctx == shares.at(0)) ? shares.at(1) : shares.at(0);
- else
- return 0;
-}
-
-QGLContextPrivate::QGLContextPrivate(QGLContext *context)
- : internal_context(false)
- , q_ptr(context)
- , texture_destroyer(0)
- , functions(0)
-{
- group = new QGLContextGroup(context);
-
- texture_destroyer = new QGLTextureDestroyer;
-}
-
-QGLContextPrivate::~QGLContextPrivate()
-{
- delete functions;
-
- if (!group->m_refs.deref()) {
- Q_ASSERT(group->context() == q_ptr);
- delete group;
- }
-
- delete texture_destroyer;
-}
-
-void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
-{
- Q_Q(QGLContext);
- glFormat = reqFormat = format;
- valid = false;
- q->setDevice(dev);
-
- guiGlContext = 0;
- ownContext = false;
- fbo = 0;
- crWin = false;
- initDone = false;
- sharing = false;
- max_texture_size = -1;
- version_flags_cached = false;
- version_flags = QGLFormat::OpenGL_Version_None;
- current_fbo = 0;
- default_fbo = 0;
- active_engine = 0;
- workaround_needsFullClearOnEveryFrame = false;
- workaround_brokenFBOReadBack = false;
- workaround_brokenTexSubImage = false;
- workaroundsCached = false;
-
- workaround_brokenTextureFromPixmap = false;
- workaround_brokenTextureFromPixmap_init = false;
-
- workaround_brokenAlphaTexSubImage = false;
- workaround_brokenAlphaTexSubImage_init = false;
-
- for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
- vertexAttributeArraysEnabledState[i] = false;
-}
-
-QGLContext* QGLContext::currentCtx = 0;
-
-/*
- QGLTemporaryContext implementation
-*/
-class QGLTemporaryContextPrivate
-{
-public:
- QWindow *window;
- QOpenGLContext *context;
-
- QGLContext *oldContext;
-};
-
-QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
- : d(new QGLTemporaryContextPrivate)
-{
- d->oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
-
- d->window = new QWindow;
- d->window->setSurfaceType(QWindow::OpenGLSurface);
- d->window->setGeometry(QRect(0, 0, 3, 3));
- d->window->create();
-
- d->context = new QOpenGLContext;
-#if !defined(QT_OPENGL_ES)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
- // On desktop, request latest released version
- QSurfaceFormat format;
-#if defined(Q_OS_MAC)
- // OS X is limited to OpenGL 3.2 Core Profile at present
- // so set that here. If we use compatibility profile it
- // only reports 2.x contexts.
- format.setMajorVersion(3);
- format.setMinorVersion(2);
- format.setProfile(QSurfaceFormat::CoreProfile);
-#else
- format.setMajorVersion(4);
- format.setMinorVersion(3);
-#endif
- d->context->setFormat(format);
- }
-#endif // QT_OPENGL_ES
- d->context->create();
- d->context->makeCurrent(d->window);
-}
-
-QGLTemporaryContext::~QGLTemporaryContext()
-{
- if (d->oldContext)
- d->oldContext->makeCurrent();
-
- delete d->context;
- delete d->window;
-}
-
-/*
- Read back the contents of the currently bound framebuffer, used in
- QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
- QGLFramebufferObject::toImage()
-*/
-
-static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
-{
- Q_ASSERT(!img.isNull());
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- // OpenGL gives RGBA; Qt wants ARGB
- uint *p = (uint*)img.bits();
- uint *end = p + w*h;
- if (alpha_format && include_alpha) {
- while (p < end) {
- uint a = *p << 24;
- *p = (*p >> 8) | a;
- p++;
- }
- } else {
- // This is an old legacy fix for PowerPC based Macs, which
- // we shouldn't remove
- while (p < end) {
- *p = 0xff000000 | (*p>>8);
- ++p;
- }
- }
- } else {
- // OpenGL gives ABGR (i.e. RGBA backwards); Qt wants ARGB
- for (int y = 0; y < h; y++) {
- uint *q = (uint*)img.scanLine(y);
- for (int x=0; x < w; ++x) {
- const uint pixel = *q;
- if (alpha_format && include_alpha) {
- *q = ((pixel << 16) & 0xff0000) | ((pixel >> 16) & 0xff)
- | (pixel & 0xff00ff00);
- } else {
- *q = 0xff000000 | ((pixel << 16) & 0xff0000)
- | ((pixel >> 16) & 0xff) | (pixel & 0x00ff00);
- }
-
- q++;
- }
- }
-
- }
- img = img.mirrored();
-}
-
-QImage qt_gl_read_frame_buffer(const QSize &size, bool alpha_format, bool include_alpha)
-{
- QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
- : QImage::Format_RGB32);
- if (img.isNull())
- return QImage();
- int w = size.width();
- int h = size.height();
- qgl_functions()->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
- convertFromGLImage(img, w, h, alpha_format, include_alpha);
- return img;
-}
-
-QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
-{
- QImage img(size, alpha_format ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);
- if (img.isNull())
- return QImage();
- int w = size.width();
- int h = size.height();
-#ifndef QT_OPENGL_ES
- if (!QOpenGLContext::currentContext()->isOpenGLES()) {
-
- qgl1_functions()->glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
- }
-#endif // QT_OPENGL_ES
- convertFromGLImage(img, w, h, alpha_format, include_alpha);
- return img;
-}
-
-Q_GLOBAL_STATIC(QGLTextureCache, qt_gl_texture_cache)
-
-QGLTextureCache::QGLTextureCache()
- : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though
-{
- QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixampData);
- QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupBeforePixmapDestruction);
- QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
-}
-
-QGLTextureCache::~QGLTextureCache()
-{
- QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixampData);
- QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupBeforePixmapDestruction);
- QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
-}
-
-void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
-{
- QWriteLocker locker(&m_lock);
- const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
- const bool inserted = m_cache.insert(cacheKey, texture, cost);
- Q_UNUSED(inserted) Q_ASSERT(inserted);
-}
-
-void QGLTextureCache::remove(qint64 key)
-{
- QWriteLocker locker(&m_lock);
- QMutexLocker groupLocker(&qt_context_groups()->m_mutex);
- QList<QGLContextGroup *>::const_iterator it = qt_context_groups()->m_list.constBegin();
- while (it != qt_context_groups()->m_list.constEnd()) {
- const QGLTextureCacheKey cacheKey = {key, *it};
- m_cache.remove(cacheKey);
- ++it;
- }
-}
-
-bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId)
-{
- QWriteLocker locker(&m_lock);
- QList<QGLTextureCacheKey> keys = m_cache.keys();
- for (int i = 0; i < keys.size(); ++i) {
- QGLTexture *tex = m_cache.object(keys.at(i));
- if (tex->id == textureId && tex->context == ctx) {
- tex->options |= QGLContext::MemoryManagedBindOption; // forces a glDeleteTextures() call
- m_cache.remove(keys.at(i));
- return true;
- }
- }
- return false;
-}
-
-void QGLTextureCache::removeContextTextures(QGLContext* ctx)
-{
- QWriteLocker locker(&m_lock);
- QList<QGLTextureCacheKey> keys = m_cache.keys();
- for (int i = 0; i < keys.size(); ++i) {
- const QGLTextureCacheKey &key = keys.at(i);
- if (m_cache.object(key)->context == ctx)
- m_cache.remove(key);
- }
-}
-
-/*
- a hook that removes textures from the cache when a pixmap/image
- is deref'ed
-*/
-void QGLTextureCache::cleanupTexturesForCacheKey(qint64 cacheKey)
-{
- qt_gl_texture_cache()->remove(cacheKey);
-}
-
-
-void QGLTextureCache::cleanupTexturesForPixampData(QPlatformPixmap* pmd)
-{
- cleanupTexturesForCacheKey(pmd->cacheKey());
-}
-
-void QGLTextureCache::cleanupBeforePixmapDestruction(QPlatformPixmap* pmd)
-{
- // Remove any bound textures first:
- cleanupTexturesForPixampData(pmd);
-}
-
-QGLTextureCache *QGLTextureCache::instance()
-{
- return qt_gl_texture_cache();
-}
-
-// DDS format structure
-struct DDSFormat {
- quint32 dwSize;
- quint32 dwFlags;
- quint32 dwHeight;
- quint32 dwWidth;
- quint32 dwLinearSize;
- quint32 dummy1;
- quint32 dwMipMapCount;
- quint32 dummy2[11];
- struct {
- quint32 dummy3[2];
- quint32 dwFourCC;
- quint32 dummy4[5];
- } ddsPixelFormat;
-};
-
-// compressed texture pixel formats
-#define FOURCC_DXT1 0x31545844
-#define FOURCC_DXT2 0x32545844
-#define FOURCC_DXT3 0x33545844
-#define FOURCC_DXT4 0x34545844
-#define FOURCC_DXT5 0x35545844
-
-// ####TODO Properly #ifdef this class to use #define symbols actually defined
-// by system GL includes
-#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
-#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
-#endif
-
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
-#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
-#endif
-
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
-#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
-#endif
-
-#ifndef GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
-#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
-#endif
-
-#ifndef GL_GENERATE_MIPMAP_SGIS
-#define GL_GENERATE_MIPMAP_SGIS 0x8191
-#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
-#endif
-
-/*!
- \class QGLContext
- \inmodule QtOpenGL
- \obsolete
-
- \brief The QGLContext class encapsulates an OpenGL rendering context.
-
- An OpenGL rendering context is a complete set of OpenGL state
- variables. The rendering context's \l {QGL::FormatOption} {format}
- is set in the constructor, but it can also be set later with
- setFormat(). The format options that are actually set are returned
- by format(); the options you asked for are returned by
- requestedFormat(). Note that after a QGLContext object has been
- constructed, the actual OpenGL context must be created by
- explicitly calling the \l{create()}
- function. The makeCurrent() function makes this context the
- current rendering context. You can make \e no context current
- using doneCurrent(). The reset() function will reset the context
- and make it invalid.
-
- You can examine properties of the context with, e.g. isValid(),
- isSharing(), initialized(), windowCreated() and
- overlayTransparentColor().
-
- If you're using double buffering you can swap the screen contents
- with the off-screen buffer using swapBuffers().
-
- Please note that QGLContext is not thread safe.
-*/
-
-/*!
- \enum QGLContext::BindOption
- \since 4.6
-
- A set of options to decide how to bind a texture using bindTexture().
-
- \value NoBindOption Don't do anything, pass the texture straight
- through.
-
- \value InvertedYBindOption Specifies that the texture should be flipped
- over the X axis so that the texture coordinate 0,0 corresponds to
- the top left corner. Inverting the texture implies a deep copy
- prior to upload.
-
- \value MipmapBindOption Specifies that bindTexture() should try
- to generate mipmaps. If the GL implementation supports the \c
- GL_SGIS_generate_mipmap extension, mipmaps will be automatically
- generated for the texture. Mipmap generation is only supported for
- the \c GL_TEXTURE_2D target.
-
- \value PremultipliedAlphaBindOption Specifies that the image should be
- uploaded with premultiplied alpha and does a conversion accordingly.
-
- \value LinearFilteringBindOption Specifies that the texture filtering
- should be set to GL_LINEAR. Default is GL_NEAREST. If mipmap is
- also enabled, filtering will be set to GL_LINEAR_MIPMAP_LINEAR.
-
- \value DefaultBindOption In Qt 4.5 and earlier, bindTexture()
- would mirror the image and automatically generate mipmaps. This
- option helps preserve this default behavior.
-
- \omitvalue CanFlipNativePixmapBindOption \omit Used by x11 from pixmap to choose
- whether or not it can bind the pixmap upside down or not. \endomit
-
- \omitvalue MemoryManagedBindOption \omit Used by paint engines to
- indicate that the pixmap should be memory managed along side with
- the pixmap/image that it stems from, e.g. installing destruction
- hooks in them. \endomit
-
- \omitvalue TemporarilyCachedBindOption \omit Used by paint engines on some
- platforms to indicate that the pixmap or image texture is possibly
- cached only temporarily and must be destroyed immediately after the use. \endomit
-
- \omitvalue InternalBindOption
-*/
-
-/*!
- \obsolete
-
- Constructs an OpenGL context for the given paint \a device, which
- can be a widget or a pixmap. The \a format specifies several
- display options for the context.
-
- If the underlying OpenGL/Window system cannot satisfy all the
- features requested in \a format, the nearest subset of features
- will be used. After creation, the format() method will return the
- actual format obtained.
-
- Note that after a QGLContext object has been constructed, \l
- create() must be called explicitly to create the actual OpenGL
- context. The context will be \l {isValid()}{invalid} if it was not
- possible to obtain a GL context at all.
-*/
-
-QGLContext::QGLContext(const QGLFormat &format, QPaintDevice *device)
- : d_ptr(new QGLContextPrivate(this))
-{
- Q_D(QGLContext);
- d->init(device, format);
-}
-
-/*!
- Constructs an OpenGL context with the given \a format which
- specifies several display options for the context.
-
- If the underlying OpenGL/Window system cannot satisfy all the
- features requested in \a format, the nearest subset of features
- will be used. After creation, the format() method will return the
- actual format obtained.
-
- Note that after a QGLContext object has been constructed, \l
- create() must be called explicitly to create the actual OpenGL
- context. The context will be \l {isValid()}{invalid} if it was not
- possible to obtain a GL context at all.
-
- \sa format(), isValid()
-*/
-QGLContext::QGLContext(const QGLFormat &format)
- : d_ptr(new QGLContextPrivate(this))
-{
- Q_D(QGLContext);
- d->init(0, format);
-}
-
-static void qDeleteQGLContext(void *handle)
-{
- QGLContext *context = static_cast<QGLContext *>(handle);
- delete context;
-}
-
-QGLContext::QGLContext(QOpenGLContext *context)
- : d_ptr(new QGLContextPrivate(this))
-{
- Q_D(QGLContext);
- d->init(0, QGLFormat::fromSurfaceFormat(context->format()));
- d->guiGlContext = context;
- d->guiGlContext->setQGLContextHandle(this, qDeleteQGLContext);
- d->ownContext = false;
- d->valid = context->isValid();
- d->setupSharing();
-}
-
-/*!
- Returns the OpenGL context handle.
-*/
-QOpenGLContext *QGLContext::contextHandle() const
-{
- Q_D(const QGLContext);
- return d->guiGlContext;
-}
-
-/*!
- Returns an OpenGL context for the window context specified by the \a context
- parameter.
-*/
-QGLContext *QGLContext::fromOpenGLContext(QOpenGLContext *context)
-{
- if (!context)
- return 0;
- if (context->qGLContextHandle()) {
- return reinterpret_cast<QGLContext *>(context->qGLContextHandle());
- }
- QGLContext *glContext = new QGLContext(context);
- //Don't call create on context. This can cause the platformFormat to be set on the widget, which
- //will cause the platformWindow to be recreated.
- return glContext;
-}
-
-/*!
- Destroys the OpenGL context and frees its resources.
-*/
-
-QGLContext::~QGLContext()
-{
- // remove any textures cached in this context
- QGLTextureCache::instance()->removeContextTextures(this);
-
- // clean up resources specific to this context
- d_ptr->cleanup();
-
- QGLSignalProxy::instance()->emitAboutToDestroyContext(this);
- reset();
-}
-
-void QGLContextPrivate::cleanup()
-{
-}
-
-#define ctx q_ptr
-void QGLContextPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
-{
- Q_Q(QGLContext);
- Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
-#ifdef glEnableVertexAttribArray
- Q_ASSERT(glEnableVertexAttribArray);
-#endif
-
- if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
- q->functions()->glDisableVertexAttribArray(arrayIndex);
-
- if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
- q->functions()->glEnableVertexAttribArray(arrayIndex);
-
- vertexAttributeArraysEnabledState[arrayIndex] = enabled;
-}
-
-void QGLContextPrivate::syncGlState()
-{
- Q_Q(QGLContext);
-#ifdef glEnableVertexAttribArray
- Q_ASSERT(glEnableVertexAttribArray);
-#endif
- for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
- if (vertexAttributeArraysEnabledState[i])
- q->functions()->glEnableVertexAttribArray(i);
- else
- q->functions()->glDisableVertexAttribArray(i);
- }
-
-}
-#undef ctx
-
-void QGLContextPrivate::swapRegion(const QRegion &)
-{
- Q_Q(QGLContext);
- q->swapBuffers();
-}
-
-/*!
- \overload
-
- Reads the compressed texture file \a fileName and generates a 2D GL
- texture from it.
-
- This function can load DirectDrawSurface (DDS) textures in the
- DXT1, DXT3 and DXT5 DDS formats if the \c GL_ARB_texture_compression
- and \c GL_EXT_texture_compression_s3tc extensions are supported.
-
- Since 4.6.1, textures in the ETC1 format can be loaded if the
- \c GL_OES_compressed_ETC1_RGB8_texture extension is supported
- and the ETC1 texture has been encapsulated in the PVR container format.
- Also, textures in the PVRTC2 and PVRTC4 formats can be loaded
- if the \c GL_IMG_texture_compression_pvrtc extension is supported.
-
- \sa deleteTexture()
-*/
-
-GLuint QGLContext::bindTexture(const QString &fileName)
-{
- QGLTexture texture(this);
- QSize size = texture.bindCompressedTexture(fileName);
- if (!size.isValid())
- return 0;
- return texture.id;
-}
-
-static inline QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format)
-{
- if (texture_format == GL_BGRA) {
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- return ((src_pixel << 24) & 0xff000000)
- | ((src_pixel >> 24) & 0x000000ff)
- | ((src_pixel << 8) & 0x00ff0000)
- | ((src_pixel >> 8) & 0x0000ff00);
- } else {
- return src_pixel;
- }
- } else { // GL_RGBA
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- return (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
- } else {
- return ((src_pixel << 16) & 0xff0000)
- | ((src_pixel >> 16) & 0xff)
- | (src_pixel & 0xff00ff00);
- }
- }
-}
-
-static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
-{
- Q_ASSERT(dst.depth() == 32);
- Q_ASSERT(img.depth() == 32);
-
- if (dst.size() != img.size()) {
- int target_width = dst.width();
- int target_height = dst.height();
- qreal sx = target_width / qreal(img.width());
- qreal sy = target_height / qreal(img.height());
-
- quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
- const uchar *srcPixels = img.constScanLine(img.height() - 1);
- int sbpl = img.bytesPerLine();
- int dbpl = dst.bytesPerLine();
-
- int ix = int(0x00010000 / sx);
- int iy = int(0x00010000 / sy);
-
- quint32 basex = int(0.5 * ix);
- quint32 srcy = int(0.5 * iy);
-
- // scale, swizzle and mirror in one loop
- while (target_height--) {
- const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
- int srcx = basex;
- for (int x=0; x<target_width; ++x) {
- dest[x] = qt_gl_convertToGLFormatHelper(src[srcx >> 16], texture_format);
- srcx += ix;
- }
- dest = (quint32 *)(((uchar *) dest) + dbpl);
- srcy += iy;
- }
- } else {
- const int width = img.width();
- const int height = img.height();
- const uint *p = (const uint*) img.scanLine(img.height() - 1);
- uint *q = (uint*) dst.scanLine(0);
-
- if (texture_format == GL_BGRA) {
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- // mirror + swizzle
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = ((*p << 24) & 0xff000000)
- | ((*p >> 24) & 0x000000ff)
- | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00);
- p++;
- q++;
- }
- p -= 2 * width;
- }
- } else {
- const uint bytesPerLine = img.bytesPerLine();
- for (int i=0; i < height; ++i) {
- memcpy(q, p, bytesPerLine);
- q += width;
- p -= width;
- }
- }
- } else {
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = (*p << 8) | ((*p >> 24) & 0xff);
- p++;
- q++;
- }
- p -= 2 * width;
- }
- } else {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
- p++;
- q++;
- }
- p -= 2 * width;
- }
- }
- }
- }
-}
-
-/*! \internal */
-QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format,
- QGLContext::BindOptions options)
-{
- Q_Q(QGLContext);
-
- const qint64 key = image.cacheKey();
- QGLTexture *texture = textureCacheLookup(key, target);
- if (texture) {
- if (image.paintingActive()) {
- // A QPainter is active on the image - take the safe route and replace the texture.
- q->deleteTexture(texture->id);
- texture = 0;
- } else {
- qgl_functions()->glBindTexture(target, texture->id);
- return texture;
- }
- }
-
- if (!texture)
- texture = bindTexture(image, target, format, key, options);
- // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
- Q_ASSERT(texture);
-
- // Enable the cleanup hooks for this image so that the texture cache entry is removed when the
- // image gets deleted:
- QImagePixmapCleanupHooks::enableCleanupHooks(image);
-
- return texture;
-}
-
-// #define QGL_BIND_TEXTURE_DEBUG
-
-// ####TODO Properly #ifdef this file to use #define symbols actually defined
-// by OpenGL/ES includes
-#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
-#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
-#endif
-
-// map from Qt's ARGB endianness-dependent format to GL's big-endian RGBA layout
-static inline void qgl_byteSwapImage(QImage &img, GLenum pixel_type)
-{
- const int width = img.width();
- const int height = img.height();
-
- if (pixel_type == GL_UNSIGNED_INT_8_8_8_8_REV
- || (pixel_type == GL_UNSIGNED_BYTE && QSysInfo::ByteOrder == QSysInfo::LittleEndian))
- {
- for (int i = 0; i < height; ++i) {
- uint *p = (uint *) img.scanLine(i);
- for (int x = 0; x < width; ++x)
- p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
- }
- } else {
- for (int i = 0; i < height; ++i) {
- uint *p = (uint *) img.scanLine(i);
- for (int x = 0; x < width; ++x)
- p[x] = (p[x] << 8) | ((p[x] >> 24) & 0xff);
- }
- }
-}
-
-QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint internalFormat,
- const qint64 key, QGLContext::BindOptions options)
-{
- Q_Q(QGLContext);
- QOpenGLFunctions *funcs = qgl_functions();
-
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf("QGLContextPrivate::bindTexture(), imageSize=(%d,%d), internalFormat =0x%x, options=%x, key=%llx\n",
- image.width(), image.height(), internalFormat, int(options), key);
- QTime time;
- time.start();
-#endif
-
-#ifndef QT_NO_DEBUG
- // Reset the gl error stack...git
- while (funcs->glGetError() != GL_NO_ERROR) ;
-#endif
-
- // Scale the pixmap if needed. GL textures needs to have the
- // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
- // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
- int tx_w = qNextPowerOfTwo(image.width() - 1);
- int tx_h = qNextPowerOfTwo(image.height() - 1);
-
- QImage img = image;
-
- if (!qgl_extensions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures)
- && !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0)
- && (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
- {
- img = img.scaled(tx_w, tx_h);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - upscaled to %dx%d (%d ms)\n", tx_w, tx_h, time.elapsed());
-
-#endif
- }
-
- GLuint filtering = options & QGLContext::LinearFilteringBindOption ? GL_LINEAR : GL_NEAREST;
-
- GLuint tx_id;
- funcs->glGenTextures(1, &tx_id);
- funcs->glBindTexture(target, tx_id);
- funcs->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filtering);
-
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- bool genMipmap = !ctx->isOpenGLES();
- if (glFormat.directRendering()
- && (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::GenerateMipmap))
- && target == GL_TEXTURE_2D
- && (options & QGLContext::MipmapBindOption))
- {
-#if !defined(QT_OPENGL_ES_2)
- if (genMipmap) {
- funcs->glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST);
- funcs->glTexParameteri(target, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
- } else {
- funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
- genMipmap = true;
- }
-#else
- funcs->glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);
- genMipmap = true;
-#endif
- funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, options & QGLContext::LinearFilteringBindOption
- ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - generating mipmaps (%d ms)\n", time.elapsed());
-#endif
- } else {
- funcs->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filtering);
- }
-
- QImage::Format target_format = img.format();
- bool premul = options & QGLContext::PremultipliedAlphaBindOption;
- bool needsbyteswap = true;
- GLenum externalFormat;
- GLuint pixel_type;
- if (target_format == QImage::Format_RGBA8888
- || target_format == QImage::Format_RGBA8888_Premultiplied
- || target_format == QImage::Format_RGBX8888) {
- externalFormat = GL_RGBA;
- pixel_type = GL_UNSIGNED_BYTE;
- needsbyteswap = false;
- } else if (qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat)) {
- externalFormat = GL_BGRA;
- needsbyteswap = false;
- if (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2)
- pixel_type = GL_UNSIGNED_INT_8_8_8_8_REV;
- else
- pixel_type = GL_UNSIGNED_BYTE;
- } else {
- externalFormat = GL_RGBA;
- pixel_type = GL_UNSIGNED_BYTE;
- }
-
- switch (target_format) {
- case QImage::Format_ARGB32:
- if (premul) {
- img = img.convertToFormat(target_format = QImage::Format_ARGB32_Premultiplied);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted ARGB32 -> ARGB32_Premultiplied (%d ms) \n", time.elapsed());
-#endif
- }
- break;
- case QImage::Format_ARGB32_Premultiplied:
- if (!premul) {
- img = img.convertToFormat(target_format = QImage::Format_ARGB32);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted ARGB32_Premultiplied -> ARGB32 (%d ms)\n", time.elapsed());
-#endif
- }
- break;
- case QImage::Format_RGBA8888:
- if (premul) {
- img = img.convertToFormat(target_format = QImage::Format_RGBA8888_Premultiplied);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted RGBA8888 -> RGBA8888_Premultiplied (%d ms) \n", time.elapsed());
-#endif
- }
- break;
- case QImage::Format_RGBA8888_Premultiplied:
- if (!premul) {
- img = img.convertToFormat(target_format = QImage::Format_RGBA8888);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted RGBA8888_Premultiplied -> RGBA8888 (%d ms) \n", time.elapsed());
-#endif
- }
- break;
- case QImage::Format_RGB16:
- pixel_type = GL_UNSIGNED_SHORT_5_6_5;
- externalFormat = GL_RGB;
- internalFormat = GL_RGB;
- needsbyteswap = false;
- break;
- case QImage::Format_RGB32:
- case QImage::Format_RGBX8888:
- break;
- default:
- // Ideally more formats would be converted directly to an RGBA8888 format,
- // but we are only guaranteed to have a fast conversion to an ARGB format.
- if (img.hasAlphaChannel()) {
- img = img.convertToFormat(premul
- ? QImage::Format_ARGB32_Premultiplied
- : QImage::Format_ARGB32);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted to 32-bit alpha format (%d ms)\n", time.elapsed());
-#endif
- } else {
- img = img.convertToFormat(QImage::Format_RGB32);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - converted to 32-bit (%d ms)\n", time.elapsed());
-#endif
- }
- }
-
- if (options & QGLContext::InvertedYBindOption) {
- if (img.isDetached()) {
- int ipl = img.bytesPerLine() / 4;
- int h = img.height();
- for (int y=0; y<h/2; ++y) {
- int *a = (int *) img.scanLine(y);
- int *b = (int *) img.scanLine(h - y - 1);
- for (int x=0; x<ipl; ++x)
- qSwap(a[x], b[x]);
- }
- } else {
- // Create a new image and copy across. If we use the
- // above in-place code then a full copy of the image is
- // made before the lines are swapped, which processes the
- // data twice. This version should only do it once.
- img = img.mirrored();
- }
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - flipped bits over y (%d ms)\n", time.elapsed());
-#endif
- }
-
- if (needsbyteswap) {
- // The only case where we end up with a depth different from
- // 32 in the switch above is for the RGB16 case, where we do
- // not need a byteswap.
- Q_ASSERT(img.depth() == 32);
- qgl_byteSwapImage(img, pixel_type);
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - did byte swapping (%d ms)\n", time.elapsed());
-#endif
- }
- if (ctx->isOpenGLES()) {
- // OpenGL/ES requires that the internal and external formats be
- // identical.
- internalFormat = externalFormat;
- }
-#ifdef QGL_BIND_TEXTURE_DEBUG
- printf(" - uploading, image.format=%d, externalFormat=0x%x, internalFormat=0x%x, pixel_type=0x%x\n",
- img.format(), externalFormat, internalFormat, pixel_type);
-#endif
-
- const QImage &constRef = img; // to avoid detach in bits()...
- funcs->glTexImage2D(target, 0, internalFormat, img.width(), img.height(), 0, externalFormat,
- pixel_type, constRef.bits());
- if (genMipmap && ctx->isOpenGLES())
- q->functions()->glGenerateMipmap(target);
-#ifndef QT_NO_DEBUG
- GLenum error = funcs->glGetError();
- if (error != GL_NO_ERROR) {
- qWarning(" - texture upload failed, error code 0x%x, enum: %d (%x)\n", error, target, target);
- }
-#endif
-
-#ifdef QGL_BIND_TEXTURE_DEBUG
- static int totalUploadTime = 0;
- totalUploadTime += time.elapsed();
- printf(" - upload done in %d ms, (accumulated: %d ms)\n", time.elapsed(), totalUploadTime);
-#endif
-
-
- // this assumes the size of a texture is always smaller than the max cache size
- int cost = img.width()*img.height()*4/1024;
- QGLTexture *texture = new QGLTexture(q, tx_id, target, options);
- QGLTextureCache::instance()->insert(q, key, texture, cost);
-
- return texture;
-}
-
-QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target)
-{
- Q_Q(QGLContext);
- QGLTexture *texture = QGLTextureCache::instance()->getTexture(q, key);
- if (texture && texture->target == target
- && (texture->context == q || QGLContext::areSharing(q, texture->context)))
- {
- return texture;
- }
- return 0;
-}
-
-/*! \internal */
-QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, QGLContext::BindOptions options)
-{
- Q_Q(QGLContext);
- QPlatformPixmap *pd = pixmap.handle();
- Q_UNUSED(pd);
-
- const qint64 key = pixmap.cacheKey();
- QGLTexture *texture = textureCacheLookup(key, target);
- if (texture) {
- if (pixmap.paintingActive()) {
- // A QPainter is active on the pixmap - take the safe route and replace the texture.
- q->deleteTexture(texture->id);
- texture = 0;
- } else {
- qgl_functions()->glBindTexture(target, texture->id);
- return texture;
- }
- }
-
- if (!texture) {
- QImage image;
- QPaintEngine* paintEngine = pixmap.paintEngine();
- if (!paintEngine || paintEngine->type() != QPaintEngine::Raster)
- image = pixmap.toImage();
- else {
- // QRasterPixmapData::toImage() will deep-copy the backing QImage if there's an active QPainter on it.
- // For performance reasons, we don't want that here, so we temporarily redirect the paint engine.
- QPaintDevice* currentPaintDevice = paintEngine->paintDevice();
- paintEngine->setPaintDevice(0);
- image = pixmap.toImage();
- paintEngine->setPaintDevice(currentPaintDevice);
- }
-
- // If the system depth is 16 and the pixmap doesn't have an alpha channel
- // then we convert it to RGB16 in the hope that it gets uploaded as a 16
- // bit texture which is much faster to access than a 32-bit one.
- if (pixmap.depth() == 16 && !image.hasAlphaChannel() )
- image = image.convertToFormat(QImage::Format_RGB16);
- texture = bindTexture(image, target, format, key, options);
- }
- // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null
- Q_ASSERT(texture);
-
- if (texture->id > 0)
- QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
-
- return texture;
-}
-
-/*! \internal */
-int QGLContextPrivate::maxTextureSize()
-{
- if (max_texture_size != -1)
- return max_texture_size;
-
- QOpenGLFunctions *funcs = qgl_functions();
- funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
-
-#ifndef QT_OPENGL_ES
- Q_Q(QGLContext);
- if (!q->contextHandle()->isOpenGLES()) {
- GLenum proxy = GL_PROXY_TEXTURE_2D;
-
- GLint size;
- GLint next = 64;
- funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
- gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
- if (size == 0) {
- return max_texture_size;
- }
- do {
- size = next;
- next = size * 2;
-
- if (next > max_texture_size)
- break;
- funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
- } while (next > size);
-
- max_texture_size = size;
- }
-#endif
-
- return max_texture_size;
-}
-
-/*!
- Returns a QGLFunctions object that is initialized for this context.
- */
-QGLFunctions *QGLContext::functions() const
-{
- QGLContextPrivate *d = const_cast<QGLContextPrivate *>(d_func());
- if (!d->functions) {
- d->functions = new QGLFunctions(this);
- d->functions->initializeGLFunctions(this);
- }
- return d->functions;
-}
-
-/*!
- Generates and binds a 2D GL texture to the current context, based
- on \a image. The generated texture id is returned and can be used in
- later \c glBindTexture() calls.
-
- \overload
-*/
-GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format)
-{
- if (image.isNull())
- return 0;
-
- Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(image, target, format, DefaultBindOption);
- return texture->id;
-}
-
-/*!
- \since 4.6
-
- Generates and binds a 2D GL texture to the current context, based
- on \a image. The generated texture id is returned and can be used
- in later \c glBindTexture() calls.
-
- The \a target parameter specifies the texture target. The default
- target is \c GL_TEXTURE_2D.
-
- The \a format parameter sets the internal format for the
- texture. The default format is \c GL_RGBA.
-
- The binding \a options are a set of options used to decide how to
- bind the texture to the context.
-
- The texture that is generated is cached, so multiple calls to
- bindTexture() with the same QImage will return the same texture
- id.
-
- Note that we assume default values for the glPixelStore() and
- glPixelTransfer() parameters.
-
- \sa deleteTexture()
-*/
-GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format, BindOptions options)
-{
- if (image.isNull())
- return 0;
-
- Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(image, target, format, options);
- return texture->id;
-}
-
-/*! \overload
-
- Generates and binds a 2D GL texture based on \a pixmap.
-*/
-GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
-{
- if (pixmap.isNull())
- return 0;
-
- Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(pixmap, target, format, DefaultBindOption);
- return texture->id;
-}
-
-/*!
- \overload
- \since 4.6
-
- Generates and binds a 2D GL texture to the current context, based
- on \a pixmap.
-*/
-GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, BindOptions options)
-{
- if (pixmap.isNull())
- return 0;
-
- Q_D(QGLContext);
- QGLTexture *texture = d->bindTexture(pixmap, target, format, options);
- return texture->id;
-}
-
-/*!
- Removes the texture identified by \a id from the texture cache,
- and calls glDeleteTextures() to delete the texture from the
- context.
-
- \sa bindTexture()
-*/
-void QGLContext::deleteTexture(GLuint id)
-{
- if (QGLTextureCache::instance()->remove(this, id))
- return;
- qgl_functions()->glDeleteTextures(1, &id);
-}
-
-void qt_add_rect_to_array(const QRectF &r, GLfloat *array)
-{
- qreal left = r.left();
- qreal right = r.right();
- qreal top = r.top();
- qreal bottom = r.bottom();
-
- array[0] = left;
- array[1] = top;
- array[2] = right;
- array[3] = top;
- array[4] = right;
- array[5] = bottom;
- array[6] = left;
- array[7] = bottom;
-}
-
-void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, GLfloat *array)
-{
- array[0] = x1;
- array[1] = y1;
- array[2] = x2;
- array[3] = y1;
- array[4] = x2;
- array[5] = y2;
- array[6] = x1;
- array[7] = y2;
-}
-
-#if !defined(QT_OPENGL_ES_2)
-
-static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
-{
- QOpenGLFunctions *funcs = qgl_functions();
- GLfloat tx = 1.0f;
- GLfloat ty = 1.0f;
-
-#ifdef QT_OPENGL_ES
- Q_UNUSED(textureWidth);
- Q_UNUSED(textureHeight);
- Q_UNUSED(textureTarget);
-#else
- if (textureTarget != GL_TEXTURE_2D && !QOpenGLContext::currentContext()->isOpenGLES()) {
- if (textureWidth == -1 || textureHeight == -1) {
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
- gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
- gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
- }
-
- tx = GLfloat(textureWidth);
- ty = GLfloat(textureHeight);
- }
-#endif
-
- GLfloat texCoordArray[4*2] = {
- 0, ty, tx, ty, tx, 0, 0, 0
- };
-
- GLfloat vertexArray[4*2];
- qt_add_rect_to_array(target, vertexArray);
-
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
- gl1funcs->glVertexPointer(2, GL_FLOAT, 0, vertexArray);
- gl1funcs->glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray);
-
- gl1funcs->glEnableClientState(GL_VERTEX_ARRAY);
- gl1funcs->glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- gl1funcs->glDisableClientState(GL_VERTEX_ARRAY);
- gl1funcs->glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-}
-
-#endif // !QT_OPENGL_ES_2
-
-/*!
- \since 4.4
-
- This function supports the following use cases:
-
- \list
- \li On OpenGL and OpenGL ES 1.x it draws the given texture, \a textureId,
- to the given target rectangle, \a target, in OpenGL model space. The
- \a textureTarget should be a 2D texture target.
- \li On OpenGL and OpenGL ES 2.x, if a painter is active, not inside a
- beginNativePainting / endNativePainting block, and uses the
- engine with type QPaintEngine::OpenGL2, the function will draw the given
- texture, \a textureId, to the given target rectangle, \a target,
- respecting the current painter state. This will let you draw a texture
- with the clip, transform, render hints, and composition mode set by the
- painter. Note that the texture target needs to be GL_TEXTURE_2D for this
- use case, and that this is the only supported use case under OpenGL ES 2.x.
- \endlist
-
-*/
-void QGLContext::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
-{
-#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_ES_2)
- if (d_ptr->active_engine &&
- d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
- QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
- if (!eng->isNativePaintingActive()) {
- QRectF src(0, 0, target.width(), target.height());
- QSize size(target.width(), target.height());
- if (eng->drawTexture(target, textureId, size, src))
- return;
- }
- }
-#endif
-
-#ifndef QT_OPENGL_ES_2
- QOpenGLFunctions *funcs = qgl_functions();
- if (!contextHandle()->isOpenGLES()) {
-#ifdef QT_OPENGL_ES
- if (textureTarget != GL_TEXTURE_2D) {
- qWarning("QGLContext::drawTexture(): texture target must be GL_TEXTURE_2D on OpenGL ES");
- return;
- }
-#else
- const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
- GLint oldTexture;
- funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
-#endif
-
- funcs->glEnable(textureTarget);
- funcs->glBindTexture(textureTarget, textureId);
-
- qDrawTextureRect(target, -1, -1, textureTarget);
-
-#ifdef QT_OPENGL_ES
- funcs->glDisable(textureTarget);
-#else
- if (!wasEnabled)
- funcs->glDisable(textureTarget);
- funcs->glBindTexture(textureTarget, oldTexture);
-#endif
- return;
- }
-#else
- Q_UNUSED(target);
- Q_UNUSED(textureId);
- Q_UNUSED(textureTarget);
-#endif
- qWarning("drawTexture() with OpenGL ES 2.0 requires an active OpenGL2 paint engine");
-}
-
-/*!
- \since 4.4
-
- This function supports the following use cases:
-
- \list
- \li By default it draws the given texture, \a textureId,
- at the given \a point in OpenGL model space. The
- \a textureTarget should be a 2D texture target.
- \li If a painter is active, not inside a
- beginNativePainting / endNativePainting block, and uses the
- engine with type QPaintEngine::OpenGL2, the function will draw the given
- texture, \a textureId, at the given \a point,
- respecting the current painter state. This will let you draw a texture
- with the clip, transform, render hints, and composition mode set by the
- painter. Note that the texture target needs to be GL_TEXTURE_2D for this
- use case.
- \endlist
-
- \note This function is not supported under any version of OpenGL ES.
-*/
-void QGLContext::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
-{
-#ifdef QT_OPENGL_ES
- Q_UNUSED(point);
- Q_UNUSED(textureId);
- Q_UNUSED(textureTarget);
-#else
- if (!contextHandle()->isOpenGLES()) {
- QOpenGLFunctions *funcs = qgl_functions();
- const bool wasEnabled = funcs->glIsEnabled(GL_TEXTURE_2D);
- GLint oldTexture;
- funcs->glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTexture);
-
- funcs->glEnable(textureTarget);
- funcs->glBindTexture(textureTarget, textureId);
-
- GLint textureWidth;
- GLint textureHeight;
-
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
- gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_WIDTH, &textureWidth);
- gl1funcs->glGetTexLevelParameteriv(textureTarget, 0, GL_TEXTURE_HEIGHT, &textureHeight);
-
- if (d_ptr->active_engine &&
- d_ptr->active_engine->type() == QPaintEngine::OpenGL2) {
- QGL2PaintEngineEx *eng = static_cast<QGL2PaintEngineEx*>(d_ptr->active_engine);
- if (!eng->isNativePaintingActive()) {
- QRectF dest(point, QSizeF(textureWidth, textureHeight));
- QRectF src(0, 0, textureWidth, textureHeight);
- QSize size(textureWidth, textureHeight);
- if (eng->drawTexture(dest, textureId, size, src))
- return;
- }
- }
-
- qDrawTextureRect(QRectF(point, QSizeF(textureWidth, textureHeight)), textureWidth, textureHeight, textureTarget);
-
- if (!wasEnabled)
- funcs->glDisable(textureTarget);
- funcs->glBindTexture(textureTarget, oldTexture);
- return;
- }
-#endif
- qWarning("drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget) not supported with OpenGL ES, use rect version instead");
-}
-
-/*!
- This function sets the limit for the texture cache to \a size,
- expressed in kilobytes.
-
- By default, the cache limit is approximately 64 MB.
-
- \sa textureCacheLimit()
-*/
-void QGLContext::setTextureCacheLimit(int size)
-{
- QGLTextureCache::instance()->setMaxCost(size);
-}
-
-/*!
- Returns the current texture cache limit in kilobytes.
-
- \sa setTextureCacheLimit()
-*/
-int QGLContext::textureCacheLimit()
-{
- return QGLTextureCache::instance()->maxCost();
-}
-
-
-/*!
- \fn QGLFormat QGLContext::format() const
-
- Returns the frame buffer format that was obtained (this may be a
- subset of what was requested).
-
- \sa requestedFormat()
-*/
-
-/*!
- \fn QGLFormat QGLContext::requestedFormat() const
-
- Returns the frame buffer format that was originally requested in
- the constructor or setFormat().
-
- \sa format()
-*/
-
-/*!
- Sets a \a format for this context. The context is \l{reset()}{reset}.
-
- Call create() to create a new GL context that tries to match the
- new format.
-
- \snippet code/src_opengl_qgl.cpp 7
-
- \sa format(), reset(), create()
-*/
-
-void QGLContext::setFormat(const QGLFormat &format)
-{
- Q_D(QGLContext);
- reset();
- d->glFormat = d->reqFormat = format;
-}
-
-/*!
- \internal
-*/
-void QGLContext::setDevice(QPaintDevice *pDev)
-{
- Q_D(QGLContext);
- // Do not touch the valid flag here. The context is either a new one and
- // valid is not yet set or it is adapted from a valid QOpenGLContext in which
- // case it must remain valid.
- d->paintDevice = pDev;
- if (d->paintDevice && (d->paintDevice->devType() != QInternal::Widget
- && d->paintDevice->devType() != QInternal::Pixmap
- && d->paintDevice->devType() != QInternal::Pbuffer)) {
- qWarning("QGLContext: Unsupported paint device type");
- }
-}
-
-/*!
- \fn bool QGLContext::isValid() const
-
- Returns \c true if a GL rendering context has been successfully
- created; otherwise returns \c false.
-*/
-
-/*!
- \fn void QGLContext::setValid(bool valid)
- \internal
-
- Forces the GL rendering context to be valid.
-*/
-
-/*!
- \fn bool QGLContext::isSharing() const
-
- Returns \c true if this context is sharing its GL context with
- another QGLContext, otherwise false is returned. Note that context
- sharing might not be supported between contexts with different
- formats.
-*/
-
-/*!
- Returns \c true if \a context1 and \a context2 are sharing their
- GL resources such as textures, shader programs, etc;
- otherwise returns \c false.
-
- \since 4.6
-*/
-bool QGLContext::areSharing(const QGLContext *context1, const QGLContext *context2)
-{
- if (!context1 || !context2)
- return false;
- return context1->d_ptr->group == context2->d_ptr->group;
-}
-
-/*!
- \fn bool QGLContext::deviceIsPixmap() const
-
- Returns \c true if the paint device of this context is a pixmap;
- otherwise returns \c false.
-
- Since Qt 5 the paint device is never actually a pixmap. renderPixmap() is
- however still simulated using framebuffer objects and readbacks, and this
- function will return \c true in this case.
-*/
-
-/*!
- \fn bool QGLContext::windowCreated() const
-
- Returns \c true if a window has been created for this context;
- otherwise returns \c false.
-
- \sa setWindowCreated()
-*/
-
-/*!
- \fn void QGLContext::setWindowCreated(bool on)
-
- If \a on is true the context has had a window created for it. If
- \a on is false no window has been created for the context.
-
- \sa windowCreated()
-*/
-
-/*!
- \fn uint QGLContext::colorIndex(const QColor& c) const
-
- \internal
-
- Returns a colormap index for the color c, in ColorIndex mode. Used
- by qglColor() and qglClearColor().
-*/
-uint QGLContext::colorIndex(const QColor&) const
-{
- return 0;
-}
-
-/*!
- \fn bool QGLContext::initialized() const
-
- Returns \c true if this context has been initialized, i.e. if
- QGLWidget::initializeGL() has been performed on it; otherwise
- returns \c false.
-
- \sa setInitialized()
-*/
-
-/*!
- \fn void QGLContext::setInitialized(bool on)
-
- If \a on is true the context has been initialized, i.e.
- QGLContext::setInitialized() has been called on it. If \a on is
- false the context has not been initialized.
-
- \sa initialized()
-*/
-
-/*!
- \fn const QGLContext* QGLContext::currentContext()
-
- Returns the current context, i.e. the context to which any OpenGL
- commands will currently be directed. Returns 0 if no context is
- current.
-
- \sa makeCurrent()
-*/
-
-/*!
- \fn QColor QGLContext::overlayTransparentColor() const
-
- If this context is a valid context in an overlay plane, returns
- the plane's transparent color. Otherwise returns an \l{QColor::isValid()}{invalid} color.
-
- The returned color's \l{QColormap::pixel()}{pixel} value is
- the index of the transparent color in the colormap of the overlay
- plane. (Naturally, the color's RGB values are meaningless.)
-
- The returned QColor object will generally work as expected only
- when passed as the argument to QGLWidget::qglColor() or
- QGLWidget::qglClearColor(). Under certain circumstances it can
- also be used to draw transparent graphics with a QPainter.
-*/
-QColor QGLContext::overlayTransparentColor() const
-{
- return QColor(); // Invalid color
-}
-
-/*!
- Creates the GL context. Returns \c true if it was successful in
- creating a valid GL rendering context on the paint device
- specified in the constructor; otherwise returns \c false (i.e. the
- context is invalid).
-
- If the OpenGL implementation on your system does not support the requested
- version of OpenGL context, then QGLContext will try to create the closest
- matching version. The actual created context properties can be queried
- using the QGLFormat returned by the format() function. For example, if
- you request a context that supports OpenGL 4.3 Core profile but the driver
- and/or hardware only supports version 3.2 Core profile contexts then you will
- get a 3.2 Core profile context.
-
- After successful creation, format() returns the set of features of
- the created GL rendering context.
-
- If \a shareContext points to a valid QGLContext, this method will
- try to establish OpenGL display list and texture object sharing
- between this context and the \a shareContext. Note that this may
- fail if the two contexts have different \l {format()} {formats}.
- Use isSharing() to see if sharing is in effect.
-
- \warning Implementation note: initialization of C++ class
- members usually takes place in the class constructor. QGLContext
- is an exception because it must be simple to customize. The
- virtual functions chooseContext() (and chooseVisual() for X11) can
- be reimplemented in a subclass to select a particular context. The
- problem is that virtual functions are not properly called during
- construction (even though this is correct C++) because C++
- constructs class hierarchies from the bottom up. For this reason
- we need a create() function.
-
- \sa chooseContext(), format(), isValid()
-*/
-
-bool QGLContext::create(const QGLContext* shareContext)
-{
- Q_D(QGLContext);
- if (!d->paintDevice && !d->guiGlContext)
- return false;
-
- reset();
- d->valid = chooseContext(shareContext);
- if (d->valid && d->paintDevice && d->paintDevice->devType() == QInternal::Widget) {
- QWidgetPrivate *wd = qt_widget_private(static_cast<QWidget *>(d->paintDevice));
- wd->usesDoubleBufferedGLContext = d->glFormat.doubleBuffer();
- }
- return d->valid;
-}
-
-bool QGLContext::isValid() const
-{
- Q_D(const QGLContext);
- return d->valid;
-}
-
-void QGLContext::setValid(bool valid)
-{
- Q_D(QGLContext);
- d->valid = valid;
-}
-
-bool QGLContext::isSharing() const
-{
- Q_D(const QGLContext);
- return d->group->isSharing();
-}
-
-QGLFormat QGLContext::format() const
-{
- Q_D(const QGLContext);
- return d->glFormat;
-}
-
-QGLFormat QGLContext::requestedFormat() const
-{
- Q_D(const QGLContext);
- return d->reqFormat;
-}
-
- QPaintDevice* QGLContext::device() const
-{
- Q_D(const QGLContext);
- return d->paintDevice;
-}
-
-bool QGLContext::deviceIsPixmap() const
-{
- Q_D(const QGLContext);
- return !d->readback_target_size.isEmpty();
-}
-
-
-bool QGLContext::windowCreated() const
-{
- Q_D(const QGLContext);
- return d->crWin;
-}
-
-
-void QGLContext::setWindowCreated(bool on)
-{
- Q_D(QGLContext);
- d->crWin = on;
-}
-
-bool QGLContext::initialized() const
-{
- Q_D(const QGLContext);
- return d->initDone;
-}
-
-void QGLContext::setInitialized(bool on)
-{
- Q_D(QGLContext);
- d->initDone = on;
-}
-
-const QGLContext* QGLContext::currentContext()
-{
- if (const QOpenGLContext *threadContext = QOpenGLContext::currentContext()) {
- return QGLContext::fromOpenGLContext(const_cast<QOpenGLContext *>(threadContext));
- }
- return 0;
-}
-
-void QGLContextPrivate::setCurrentContext(QGLContext *context)
-{
- Q_UNUSED(context);
-}
-
-/*!
- Moves the QGLContext to the given \a thread.
-
- Enables calling swapBuffers() and makeCurrent() on the context in
- the given thread.
-*/
-void QGLContext::moveToThread(QThread *thread)
-{
- Q_D(QGLContext);
- if (d->guiGlContext)
- d->guiGlContext->moveToThread(thread);
-}
-
-/*!
- \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0)
-
- This semi-internal function is called by create(). It creates a
- system-dependent OpenGL handle that matches the format() of \a
- shareContext as closely as possible, returning true if successful
- or false if a suitable handle could not be found.
-
- On Windows, it calls the virtual function choosePixelFormat(),
- which finds a matching pixel format identifier. On X11, it calls
- the virtual function chooseVisual() which finds an appropriate X
- visual. On other platforms it may work differently.
-*/
-bool QGLContext::chooseContext(const QGLContext* shareContext)
-{
- Q_D(QGLContext);
- if(!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) {
- // Unlike in Qt 4, the only possible target is a widget backed by an OpenGL-based
- // QWindow. Pixmaps in particular are not supported anymore as paint devices since
- // starting from Qt 5 QPixmap is raster-backed on almost all platforms.
- d->valid = false;
- }else {
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- QGLFormat glformat = format();
- QSurfaceFormat winFormat = QGLFormat::toSurfaceFormat(glformat);
- if (widget->testAttribute(Qt::WA_TranslucentBackground))
- winFormat.setAlphaBufferSize(qMax(winFormat.alphaBufferSize(), 8));
-
- QWindow *window = widget->windowHandle();
- if (!window->handle()
- || window->surfaceType() != QWindow::OpenGLSurface
- || window->requestedFormat() != winFormat)
- {
- window->setSurfaceType(QWindow::OpenGLSurface);
- window->setFormat(winFormat);
- window->destroy();
- window->create();
- }
-
- if (d->ownContext)
- delete d->guiGlContext;
- d->ownContext = true;
- QOpenGLContext *shareGlContext = shareContext ? shareContext->d_func()->guiGlContext : 0;
- d->guiGlContext = new QOpenGLContext;
- d->guiGlContext->setFormat(winFormat);
- d->guiGlContext->setShareContext(shareGlContext);
- d->valid = d->guiGlContext->create();
-
- if (d->valid)
- d->guiGlContext->setQGLContextHandle(this, 0);
-
- d->glFormat = QGLFormat::fromSurfaceFormat(d->guiGlContext->format());
- d->setupSharing();
- }
-
-
- return d->valid;
-}
-
-/*!
- \fn void QGLContext::reset()
-
- Resets the context and makes it invalid.
-
- \sa create(), isValid()
-*/
-void QGLContext::reset()
-{
- Q_D(QGLContext);
- if (!d->valid)
- return;
- d->cleanup();
-
- d->crWin = false;
- d->sharing = false;
- d->valid = false;
- d->transpColor = QColor();
- d->initDone = false;
- QGLContextGroup::removeShare(this);
- if (d->guiGlContext) {
- if (QOpenGLContext::currentContext() == d->guiGlContext)
- doneCurrent();
- if (d->ownContext) {
- if (d->guiGlContext->thread() == QThread::currentThread())
- delete d->guiGlContext;
- else
- d->guiGlContext->deleteLater();
- } else
- d->guiGlContext->setQGLContextHandle(0,0);
- d->guiGlContext = 0;
- }
- d->ownContext = false;
-}
-
-/*!
- \fn void QGLContext::makeCurrent()
-
- Makes this context the current OpenGL rendering context. All GL
- functions you call operate on this context until another context
- is made current.
-
- In some very rare cases the underlying call may fail. If this
- occurs an error message is output to stderr.
-
- If you call this from a thread other than the main UI thread,
- make sure you've first pushed the context to the relevant thread
- from the UI thread using moveToThread().
-*/
-void QGLContext::makeCurrent()
-{
- Q_D(QGLContext);
- if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
- return;
-
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- if (!widget->windowHandle())
- return;
-
- if (d->guiGlContext->makeCurrent(widget->windowHandle())) {
- if (!d->workaroundsCached) {
- d->workaroundsCached = true;
- const char *renderer = reinterpret_cast<const char *>(d->guiGlContext->functions()->glGetString(GL_RENDERER));
- if (renderer && strstr(renderer, "Mali")) {
- d->workaround_brokenFBOReadBack = true;
- }
- }
- }
-}
-
-/*!
- \fn void QGLContext::swapBuffers() const
-
- Call this to finish a frame of OpenGL rendering, and make sure to
- call makeCurrent() again before issuing any further OpenGL commands,
- for example as part of a new frame.
-*/
-void QGLContext::swapBuffers() const
-{
- Q_D(const QGLContext);
- if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget)
- return;
-
- QWidget *widget = static_cast<QWidget *>(d->paintDevice);
- if (!widget->windowHandle())
- return;
-
- d->guiGlContext->swapBuffers(widget->windowHandle());
-}
-
-/*!
- \fn void QGLContext::doneCurrent()
-
- Makes no GL context the current context. Normally, you do not need
- to call this function; QGLContext calls it as necessary.
-*/
-void QGLContext::doneCurrent()
-{
- Q_D(QGLContext);
- d->guiGlContext->doneCurrent();
-}
-
-/*!
- \fn QPaintDevice* QGLContext::device() const
-
- Returns the paint device set for this context.
-
- \sa QGLContext::QGLContext()
-*/
-
-/*****************************************************************************
- QGLWidget implementation
- *****************************************************************************/
-
-
-/*!
- \class QGLWidget
- \inmodule QtOpenGL
- \obsolete
-
- \brief The QGLWidget class is a widget for rendering OpenGL graphics.
-
- QGLWidget provides functionality for displaying OpenGL graphics
- integrated into a Qt application. It is very simple to use. You
- inherit from it and use the subclass like any other QWidget,
- except that you have the choice between using QPainter and
- standard OpenGL rendering commands.
-
- \note This class is part of the legacy \l {Qt OpenGL} module and,
- like the other \c QGL classes, should be avoided in the new
- applications. Instead, starting from Qt 5.4, prefer using
- QOpenGLWidget and the \c QOpenGL classes.
-
- QGLWidget provides three convenient virtual functions that you can
- reimplement in your subclass to perform the typical OpenGL tasks:
-
- \list
- \li paintGL() - Renders the OpenGL scene. Gets called whenever the widget
- needs to be updated.
- \li resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
- called whenever the widget has been resized (and also when it
- is shown for the first time because all newly created widgets get a
- resize event automatically).
- \li initializeGL() - Sets up the OpenGL rendering context, defines display
- lists, etc. Gets called once before the first time resizeGL() or
- paintGL() is called.
- \endlist
-
- Here is a rough outline of how a QGLWidget subclass might look:
-
- \snippet code/src_opengl_qgl.cpp 8
-
- If you need to trigger a repaint from places other than paintGL()
- (a typical example is when using \l{QTimer}{timers} to
- animate scenes), you should call the widget's updateGL() function.
-
- Your widget's OpenGL rendering context is made current when
- paintGL(), resizeGL(), or initializeGL() is called. If you need to
- call the standard OpenGL API functions from other places (e.g. in
- your widget's constructor or in your own paint functions), you
- must call makeCurrent() first.
-
- QGLWidget provides functions for requesting a new display
- \l{QGLFormat}{format} and you can also create widgets with
- customized rendering \l{QGLContext}{contexts}.
-
- You can also share OpenGL display lists between QGLWidget objects (see
- the documentation of the QGLWidget constructors for details).
-
- Note that under Windows, the QGLContext belonging to a QGLWidget
- has to be recreated when the QGLWidget is reparented. This is
- necessary due to limitations on the Windows platform. This will
- most likely cause problems for users that have subclassed and
- installed their own QGLContext on a QGLWidget. It is possible to
- work around this issue by putting the QGLWidget inside a dummy
- widget and then reparenting the dummy widget, instead of the
- QGLWidget. This will side-step the issue altogether, and is what
- we recommend for users that need this kind of functionality.
-
- On \macos, when Qt is built with Cocoa support, a QGLWidget
- can't have any sibling widgets placed ontop of itself. This is due
- to limitations in the Cocoa API and is not supported by Apple.
-
- \section1 Overlays
-
- The QGLWidget creates a GL overlay context in addition to the
- normal context if overlays are supported by the underlying system.
-
- If you want to use overlays, you specify it in the
- \l{QGLFormat}{format}. (Note: Overlay must be requested in the format
- passed to the QGLWidget constructor.) Your GL widget should also
- implement some or all of these virtual methods:
-
- \list
- \li paintOverlayGL()
- \li resizeOverlayGL()
- \li initializeOverlayGL()
- \endlist
-
- These methods work in the same way as the normal paintGL() etc.
- functions, except that they will be called when the overlay
- context is made current. You can explicitly make the overlay
- context current by using makeOverlayCurrent(), and you can access
- the overlay context directly (e.g. to ask for its transparent
- color) by calling overlayContext().
-
- On X servers in which the default visual is in an overlay plane,
- non-GL Qt windows can also be used for overlays.
-
- \section1 Painting Techniques
-
- As described above, subclass QGLWidget to render pure 3D content in the
- following way:
-
- \list
- \li Reimplement the QGLWidget::initializeGL() and QGLWidget::resizeGL() to
- set up the OpenGL state and provide a perspective transformation.
- \li Reimplement QGLWidget::paintGL() to paint the 3D scene, calling only
- OpenGL functions to draw on the widget.
- \endlist
-
- It is also possible to draw 2D graphics onto a QGLWidget subclass, it is necessary
- to reimplement QGLWidget::paintEvent() and do the following:
-
- \list
- \li Construct a QPainter object.
- \li Initialize it for use on the widget with the QPainter::begin() function.
- \li Draw primitives using QPainter's member functions.
- \li Call QPainter::end() to finish painting.
- \endlist
-
- \section1 Threading
-
- As of Qt version 4.8, support for doing threaded GL rendering has
- been improved. There are three scenarios that we currently support:
- \list
- \li 1. Buffer swapping in a thread.
-
- Swapping buffers in a double buffered context may be a
- synchronous, locking call that may be a costly operation in some
- GL implementations. Especially so on embedded devices. It's not
- optimal to have the CPU idling while the GPU is doing a buffer
- swap. In those cases it is possible to do the rendering in the
- main thread and do the actual buffer swap in a separate
- thread. This can be done with the following steps:
-
- 1. Call doneCurrent() in the main thread when the rendering is
- finished.
-
- 2. Call QGLContext::moveToThread(swapThread) to transfer ownership
- of the context to the swapping thread.
-
- 3. Notify the swapping thread that it can grab the context.
-
- 4. Make the rendering context current in the swapping thread with
- makeCurrent() and then call swapBuffers().
-
- 5. Call doneCurrent() in the swapping thread.
-
- 6. Call QGLContext::moveToThread(qApp->thread()) and notify the
- main thread that swapping is done.
-
- Doing this will free up the main thread so that it can continue
- with, for example, handling UI events or network requests. Even if
- there is a context swap involved, it may be preferable compared to
- having the main thread wait while the GPU finishes the swap
- operation. Note that this is highly implementation dependent.
-
- \li 2. Texture uploading in a thread.
-
- Doing texture uploads in a thread may be very useful for
- applications handling large amounts of images that needs to be
- displayed, like for instance a photo gallery application. This is
- supported in Qt through the existing bindTexture() API. A simple
- way of doing this is to create two sharing QGLWidgets. One is made
- current in the main GUI thread, while the other is made current in
- the texture upload thread. The widget in the uploading thread is
- never shown, it is only used for sharing textures with the main
- thread. For each texture that is bound via bindTexture(), notify
- the main thread so that it can start using the texture.
-
- \li 3. Using QPainter to draw into a QGLWidget in a thread.
-
- In Qt 4.8, it is possible to draw into a QGLWidget using a
- QPainter in a separate thread. Note that this is also possible for
- QGLPixelBuffers and QGLFramebufferObjects. Since this is only
- supported in the GL 2 paint engine, OpenGL 2.0 or OpenGL ES 2.0 is
- required.
-
- QGLWidgets can only be created in the main GUI thread. This means
- a call to doneCurrent() is necessary to release the GL context
- from the main thread, before the widget can be drawn into by
- another thread. You then need to call QGLContext::moveToThread()
- to transfer ownership of the context to the thread in which you
- want to make it current.
- Also, the main GUI thread will dispatch resize and
- paint events to a QGLWidget when the widget is resized, or parts
- of it becomes exposed or needs redrawing. It is therefore
- necessary to handle those events because the default
- implementations inside QGLWidget will try to make the QGLWidget's
- context current, which again will interfere with any threads
- rendering into the widget. Reimplement QGLWidget::paintEvent() and
- QGLWidget::resizeEvent() to notify the rendering thread that a
- resize or update is necessary, and be careful not to call the base
- class implementation. If you are rendering an animation, it might
- not be necessary to handle the paint event at all since the
- rendering thread is doing regular updates. Then it would be enough
- to reimplement QGLWidget::paintEvent() to do nothing.
-
- \endlist
-
- As a general rule when doing threaded rendering: be aware that
- binding and releasing contexts in different threads have to be
- synchronized by the user. A GL rendering context can only be
- current in one thread at any time. If you try to open a QPainter
- on a QGLWidget and the widget's rendering context is current in
- another thread, it will fail.
-
- In addition to this, rendering using raw GL calls in a separate
- thread is supported.
-
- \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
- countries.}
-
- \sa QOpenGLWidget, QGLPixelBuffer
-*/
-
-/*!
- Constructs an OpenGL widget with a \a parent widget.
-
- The \l{QGLFormat::defaultFormat()}{default format} is
- used. The widget will be \l{isValid()}{invalid} if the
- system has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
-
- The \a parent and widget flag, \a f, arguments are passed
- to the QWidget constructor.
-
- If \a shareWidget is a valid QGLWidget, this widget will share
- OpenGL display lists and texture objects with \a shareWidget. But
- if \a shareWidget and this widget have different \l {format()}
- {formats}, sharing might not be possible. You can check whether
- sharing is in effect by calling isSharing().
-
- The initialization of OpenGL rendering state, etc. should be done
- by overriding the initializeGL() function, rather than in the
- constructor of your QGLWidget subclass.
-
- \sa QGLFormat::defaultFormat(), {Textures Example}
-*/
-
-QGLWidget::QGLWidget(QWidget *parent, const QGLWidget* shareWidget, Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f)
-{
- Q_D(QGLWidget);
- d->init(new QGLContext(QGLFormat::defaultFormat(), this), shareWidget);
-}
-
-/*!
- \internal
- */
-QGLWidget::QGLWidget(QGLWidgetPrivate &dd, const QGLFormat &format, QWidget *parent, const QGLWidget *shareWidget, Qt::WindowFlags f)
- : QWidget(dd, parent, f)
-{
- Q_D(QGLWidget);
- d->init(new QGLContext(format, this), shareWidget);
-
-}
-
-
-/*!
- Constructs an OpenGL widget with parent \a parent.
-
- The \a format argument specifies the desired
- \l{QGLFormat}{rendering options}.
- If the underlying OpenGL/Window system
- cannot satisfy all the features requested in \a format, the
- nearest subset of features will be used. After creation, the
- format() method will return the actual format obtained.
-
- The widget will be \l{isValid()}{invalid} if the system
- has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
-
- The \a parent and widget flag, \a f, arguments are passed
- to the QWidget constructor.
-
- If \a shareWidget is a valid QGLWidget, this widget will share
- OpenGL display lists and texture objects with \a shareWidget. But
- if \a shareWidget and this widget have different \l {format()}
- {formats}, sharing might not be possible. You can check whether
- sharing is in effect by calling isSharing().
-
- The initialization of OpenGL rendering state, etc. should be done
- by overriding the initializeGL() function, rather than in the
- constructor of your QGLWidget subclass.
-
- \sa QGLFormat::defaultFormat(), isValid()
-*/
-
-QGLWidget::QGLWidget(const QGLFormat &format, QWidget *parent, const QGLWidget* shareWidget,
- Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f)
-{
- Q_D(QGLWidget);
- d->init(new QGLContext(format, this), shareWidget);
-}
-
-/*!
- Constructs an OpenGL widget with parent \a parent.
-
- The \a context argument is a pointer to the QGLContext that
- you wish to be bound to this widget. This allows you to pass in
- your own QGLContext sub-classes.
-
- The widget will be \l{isValid()}{invalid} if the system
- has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
-
- The \a parent and widget flag, \a f, arguments are passed
- to the QWidget constructor.
-
- If \a shareWidget is a valid QGLWidget, this widget will share
- OpenGL display lists and texture objects with \a shareWidget. But
- if \a shareWidget and this widget have different \l {format()}
- {formats}, sharing might not be possible. You can check whether
- sharing is in effect by calling isSharing().
-
- The initialization of OpenGL rendering state, etc. should be done
- by overriding the initializeGL() function, rather than in the
- constructor of your QGLWidget subclass.
-
- \sa QGLFormat::defaultFormat(), isValid()
-*/
-QGLWidget::QGLWidget(QGLContext *context, QWidget *parent, const QGLWidget *shareWidget,
- Qt::WindowFlags f)
- : QWidget(*(new QGLWidgetPrivate), parent, f)
-{
- Q_D(QGLWidget);
- d->init(context, shareWidget);
-}
-
-/*!
- Destroys the widget.
-*/
-
-QGLWidget::~QGLWidget()
-{
- Q_D(QGLWidget);
- delete d->glcx;
- d->glcx = 0;
- d->cleanupColormaps();
-}
-
-/*!
- \fn QGLFormat QGLWidget::format() const
-
- Returns the format of the contained GL rendering context.
-*/
-
-/*!
- \fn bool QGLWidget::doubleBuffer() const
-
- Returns \c true if the contained GL rendering context has double
- buffering; otherwise returns \c false.
-
- \sa QGLFormat::doubleBuffer()
-*/
-
-/*!
- \fn void QGLWidget::setAutoBufferSwap(bool on)
-
- If \a on is true automatic GL buffer swapping is switched on;
- otherwise it is switched off.
-
- If \a on is true and the widget is using a double-buffered format,
- the background and foreground GL buffers will automatically be
- swapped after each paintGL() call.
-
- The buffer auto-swapping is on by default.
-
- \sa autoBufferSwap(), doubleBuffer(), swapBuffers()
-*/
-
-/*!
- \fn bool QGLWidget::autoBufferSwap() const
-
- Returns \c true if the widget is doing automatic GL buffer swapping;
- otherwise returns \c false.
-
- \sa setAutoBufferSwap()
-*/
-
-/*!
- \fn QFunctionPointer QGLContext::getProcAddress(const QString &proc) const
-
- Returns a function pointer to the GL extension function passed in
- \a proc. \nullptr is returned if a pointer to the function could not be
- obtained.
-*/
-QFunctionPointer QGLContext::getProcAddress(const QString &procName) const
-{
- Q_D(const QGLContext);
- return d->guiGlContext->getProcAddress(procName.toLatin1());
-}
-
-/*!
- \fn bool QGLWidget::isValid() const
-
- Returns \c true if the widget has a valid GL rendering context;
- otherwise returns \c false. A widget will be invalid if the system
- has no \l{QGLFormat::hasOpenGL()}{OpenGL support}.
-*/
-
-bool QGLWidget::isValid() const
-{
- Q_D(const QGLWidget);
- return d->glcx && d->glcx->isValid();
-}
-
-/*!
- \fn bool QGLWidget::isSharing() const
-
- Returns \c true if this widget's GL context is shared with another GL
- context, otherwise false is returned. Context sharing might not be
- possible if the widgets use different formats.
-
- \sa format()
-*/
-
-bool QGLWidget::isSharing() const
-{
- Q_D(const QGLWidget);
- return d->glcx->isSharing();
-}
-
-/*!
- \fn void QGLWidget::makeCurrent()
-
- Makes this widget the current widget for OpenGL operations, i.e.
- makes the widget's rendering context the current OpenGL rendering
- context.
-*/
-
-void QGLWidget::makeCurrent()
-{
- Q_D(QGLWidget);
- d->makeCurrent();
-}
-
-bool QGLWidgetPrivate::makeCurrent()
-{
- glcx->makeCurrent();
- return QGLContext::currentContext() == glcx;
-}
-
-/*!
- \fn void QGLWidget::doneCurrent()
-
- Makes no GL context the current context. Normally, you do not need
- to call this function; QGLContext calls it as necessary. However,
- it may be useful in multithreaded environments.
-*/
-
-void QGLWidget::doneCurrent()
-{
- Q_D(QGLWidget);
- d->glcx->doneCurrent();
-}
-
-/*!
- \fn void QGLWidget::swapBuffers()
-
- Swaps the screen contents with an off-screen buffer. This only
- works if the widget's format specifies double buffer mode.
-
- Normally, there is no need to explicitly call this function
- because it is done automatically after each widget repaint, i.e.
- each time after paintGL() has been executed.
-
- \sa doubleBuffer(), setAutoBufferSwap(), QGLFormat::setDoubleBuffer()
-*/
-
-void QGLWidget::swapBuffers()
-{
- Q_D(QGLWidget);
- d->glcx->swapBuffers();
-}
-
-
-/*!
- \fn const QGLContext* QGLWidget::overlayContext() const
-
- Returns the overlay context of this widget, or \nullptr if this
- widget has no overlay.
-
- \sa context()
-*/
-const QGLContext* QGLWidget::overlayContext() const
-{
- return nullptr;
-}
-
-/*!
- \fn void QGLWidget::makeOverlayCurrent()
-
- Makes the overlay context of this widget current. Use this if you
- need to issue OpenGL commands to the overlay context outside of
- initializeOverlayGL(), resizeOverlayGL(), and paintOverlayGL().
-
- Does nothing if this widget has no overlay.
-
- \sa makeCurrent()
-*/
-void QGLWidget::makeOverlayCurrent()
-{
-}
-
-/*!
- \obsolete
-
- Sets a new format for this widget.
-
- If the underlying OpenGL/Window system cannot satisfy all the
- features requested in \a format, the nearest subset of features will
- be used. After creation, the format() method will return the actual
- rendering context format obtained.
-
- The widget will be assigned a new QGLContext, and the initializeGL()
- function will be executed for this new context before the first
- resizeGL() or paintGL().
-
- This method will try to keep display list and texture object sharing
- in effect with other QGLWidget objects, but changing the format might make
- sharing impossible. Use isSharing() to see if sharing is still in
- effect.
-
- \sa format(), isSharing(), isValid()
-*/
-
-void QGLWidget::setFormat(const QGLFormat &format)
-{
- setContext(new QGLContext(format,this));
-}
-
-
-
-
-/*!
- \fn QGLContext *QGLWidget::context() const
-
- Returns the context of this widget.
-
- It is possible that the context is not valid (see isValid()), for
- example, if the underlying hardware does not support the format
- attributes that were requested.
-*/
-
-/*!
- \fn void QGLWidget::setContext(QGLContext *context,
- const QGLContext* shareContext,
- bool deleteOldContext)
- \obsolete
-
- Sets a new context for this widget. The QGLContext \a context must
- be created using \e new. QGLWidget will delete \a context when
- another context is set or when the widget is destroyed.
-
- If \a context is invalid, QGLContext::create() is performed on
- it. The initializeGL() function will then be executed for the new
- context before the first resizeGL() or paintGL().
-
- If \a context is invalid, this method will try to keep display list
- and texture object sharing in effect, or (if \a shareContext points
- to a valid context) start display list and texture object sharing
- with that context, but sharing might be impossible if the two
- contexts have different \l {format()} {formats}. Use isSharing() to
- see whether sharing is in effect.
-
- If \a deleteOldContext is true (the default), the existing context
- will be deleted. You may use false here if you have kept a pointer
- to the old context (as returned by context()), and want to restore
- that context later.
-
- \note This function is obsolete and should no longer be used. If you were
- using it to recreate the context for a QGLWidget, you should instead create a
- new QGLWidget or use the QOpenGLContext API in conjunction with QWindow.
- There is currently no officially supported way to substitute QGLWidget's
- context with your own implementation of QGLContext.
-
- \sa context(), isSharing()
-*/
-void QGLWidget::setContext(QGLContext *context,
- const QGLContext* shareContext,
- bool deleteOldContext)
-{
- Q_D(QGLWidget);
- if (context == 0) {
- qWarning("QGLWidget::setContext: Cannot set null context");
- return;
- }
-
- if (context->device() == 0) // a context may refere to more than 1 window.
- context->setDevice(this); //but its better to point to 1 of them than none of them.
-
- QGLContext* oldcx = d->glcx;
- d->glcx = context;
-
- if (!d->glcx->isValid())
- d->glcx->create(shareContext ? shareContext : oldcx);
-
- if (deleteOldContext)
- delete oldcx;
-}
-
-/*!
- \fn void QGLWidget::updateGL()
-
- Updates the widget by calling glDraw().
-*/
-
-void QGLWidget::updateGL()
-{
- Q_D(QGLWidget);
- const bool targetIsOffscreen = !d->glcx->d_ptr->readback_target_size.isEmpty();
- if (updatesEnabled() && (testAttribute(Qt::WA_Mapped) || targetIsOffscreen))
- glDraw();
-}
-
-
-/*!
- \fn void QGLWidget::updateOverlayGL()
-
- Updates the widget's overlay (if any). Will cause the virtual
- function paintOverlayGL() to be executed.
-
- The widget's rendering context will become the current context and
- initializeGL() will be called if it hasn't already been called.
-*/
-void QGLWidget::updateOverlayGL()
-{
-}
-
-/*!
- This virtual function is called once before the first call to
- paintGL() or resizeGL(), and then once whenever the widget has
- been assigned a new QGLContext. Reimplement it in a subclass.
-
- This function should set up any required OpenGL context rendering
- flags, defining display lists, etc.
-
- There is no need to call makeCurrent() because this has already
- been done when this function is called.
-*/
-
-void QGLWidget::initializeGL()
-{
-}
-
-
-/*!
- This virtual function is called whenever the widget needs to be
- painted. Reimplement it in a subclass.
-
- There is no need to call makeCurrent() because this has already
- been done when this function is called.
-*/
-
-void QGLWidget::paintGL()
-{
- qgl_functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-
-/*!
- \fn void QGLWidget::resizeGL(int width , int height)
-
- This virtual function is called whenever the widget has been
- resized. The new size is passed in \a width and \a height.
- Reimplement it in a subclass.
-
- There is no need to call makeCurrent() because this has already
- been done when this function is called.
-*/
-
-void QGLWidget::resizeGL(int, int)
-{
-}
-
-
-
-/*!
- This virtual function is used in the same manner as initializeGL()
- except that it operates on the widget's overlay context instead of
- the widget's main context. This means that initializeOverlayGL()
- is called once before the first call to paintOverlayGL() or
- resizeOverlayGL(). Reimplement it in a subclass.
-
- This function should set up any required OpenGL context rendering
- flags, defining display lists, etc. for the overlay context.
-
- There is no need to call makeOverlayCurrent() because this has
- already been done when this function is called.
-*/
-
-void QGLWidget::initializeOverlayGL()
-{
-}
-
-
-/*!
- This virtual function is used in the same manner as paintGL()
- except that it operates on the widget's overlay context instead of
- the widget's main context. This means that paintOverlayGL() is
- called whenever the widget's overlay needs to be painted.
- Reimplement it in a subclass.
-
- There is no need to call makeOverlayCurrent() because this has
- already been done when this function is called.
-*/
-
-void QGLWidget::paintOverlayGL()
-{
-}
-
-
-/*!
- \fn void QGLWidget::resizeOverlayGL(int width , int height)
-
- This virtual function is used in the same manner as paintGL()
- except that it operates on the widget's overlay context instead of
- the widget's main context. This means that resizeOverlayGL() is
- called whenever the widget has been resized. The new size is
- passed in \a width and \a height. Reimplement it in a subclass.
-
- There is no need to call makeOverlayCurrent() because this has
- already been done when this function is called.
-*/
-
-void QGLWidget::resizeOverlayGL(int, int)
-{
-}
-
-/*!\reimp
-*/
-bool QGLWidget::event(QEvent *e)
-{
- Q_D(QGLWidget);
-
- // A re-parent will destroy the window and re-create it. We should not reset the context while it happens.
- if (e->type() == QEvent::ParentAboutToChange)
- d->parent_changing = true;
-
- if (e->type() == QEvent::ParentChange)
- d->parent_changing = false;
-
- return QWidget::event(e);
-}
-
-/*!
- \fn void QGLWidget::paintEvent(QPaintEvent *event)
-
- Handles paint events passed in the \a event parameter. Will cause
- the virtual paintGL() function to be called.
-
- The widget's rendering context will become the current context and
- initializeGL() will be called if it hasn't already been called.
-*/
-
-void QGLWidget::paintEvent(QPaintEvent *)
-{
- if (updatesEnabled()) {
- glDraw();
- updateOverlayGL();
- }
-}
-
-
-/*!
- \fn void QGLWidget::resizeEvent(QResizeEvent *event)
-
- Handles resize events that are passed in the \a event parameter.
- Calls the virtual function resizeGL().
-*/
-void QGLWidget::resizeEvent(QResizeEvent *e)
-{
- Q_D(QGLWidget);
-
- QWidget::resizeEvent(e);
- if (!isValid())
- return;
- if (!d->makeCurrent())
- return;
- if (!d->glcx->initialized())
- glInit();
- const qreal scaleFactor = (window() && window()->windowHandle()) ?
- window()->windowHandle()->devicePixelRatio() : 1.0;
-
- resizeGL(width() * scaleFactor, height() * scaleFactor);
-}
-
-/*!
- Renders the current scene on a pixmap and returns the pixmap.
-
- You can use this method on both visible and invisible QGLWidget objects.
-
- Internally the function renders into a framebuffer object and performs pixel
- readback. This has a performance penalty, meaning that this function is not
- suitable to be called at a high frequency.
-
- After creating and binding the framebuffer object, the function will call
- initializeGL(), resizeGL(), and paintGL(). On the next normal update
- initializeGL() and resizeGL() will be triggered again since the size of the
- destination pixmap and the QGLWidget's size may differ.
-
- The size of the pixmap will be \a w pixels wide and \a h pixels high unless
- one of these parameters is 0 (the default), in which case the pixmap will
- have the same size as the widget.
-
- Care must be taken when using framebuffer objects in paintGL() in
- combination with this function. To switch back to the default framebuffer,
- use QGLFramebufferObject::bindDefault(). Binding FBO 0 is wrong since
- renderPixmap() uses a custom framebuffer instead of the one provided by the
- windowing system.
-
- \a useContext is ignored. Historically this parameter enabled the usage of
- the existing GL context. This is not supported anymore since additional
- contexts are never created.
-
- Overlays are not rendered onto the pixmap.
-
- If the GL rendering context and the desktop have different bit
- depths, the result will most likely look surprising.
-
- Note that the creation of display lists, modifications of the view
- frustum etc. should be done from within initializeGL(). If this is
- not done, the temporary QGLContext will not be initialized
- properly, and the rendered pixmap may be incomplete/corrupted.
-*/
-
-QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext)
-{
- Q_UNUSED(useContext);
- Q_D(QGLWidget);
-
- QSize sz = size();
- if ((w > 0) && (h > 0))
- sz = QSize(w, h);
-
- QPixmap pm;
- if (d->glcx->isValid()) {
- d->glcx->makeCurrent();
- QGLFramebufferObject fbo(sz, QGLFramebufferObject::CombinedDepthStencil);
- fbo.bind();
- d->glcx->setInitialized(false);
- uint prevDefaultFbo = d->glcx->d_ptr->default_fbo;
- d->glcx->d_ptr->default_fbo = fbo.handle();
- d->glcx->d_ptr->readback_target_size = sz;
- updateGL();
- fbo.release();
- pm = QPixmap::fromImage(fbo.toImage());
- d->glcx->d_ptr->default_fbo = prevDefaultFbo;
- d->glcx->setInitialized(false);
- d->glcx->d_ptr->readback_target_size = QSize();
- }
-
- return pm;
-}
-
-/*!
- Returns an image of the frame buffer. If \a withAlpha is true the
- alpha channel is included.
-
- Depending on your hardware, you can explicitly select which color
- buffer to grab with a glReadBuffer() call before calling this
- function.
-
- On QNX the back buffer is not preserved when swapBuffers() is called. The back buffer
- where this function reads from, might thus not contain the same content as the front buffer.
- In order to retrieve what is currently visible on the screen, swapBuffers()
- has to be executed prior to this function call.
-*/
-QImage QGLWidget::grabFrameBuffer(bool withAlpha)
-{
- makeCurrent();
- QImage res;
- qreal pixelRatio = devicePixelRatioF();
- int w = pixelRatio * width();
- int h = pixelRatio * height();
- if (format().rgba())
- res = qt_gl_read_frame_buffer(QSize(w, h), format().alpha(), withAlpha);
- res.setDevicePixelRatio(pixelRatio);
- return res;
-}
-
-
-
-/*!
- Initializes OpenGL for this widget's context. Calls the virtual
- function initializeGL().
-*/
-
-void QGLWidget::glInit()
-{
- Q_D(QGLWidget);
- if (!isValid())
- return;
- if (!d->makeCurrent())
- return;
- initializeGL();
- d->glcx->setInitialized(true);
-}
-
-
-/*!
- Executes the virtual function paintGL().
-
- The widget's rendering context will become the current context and
- initializeGL() will be called if it hasn't already been called.
-*/
-
-void QGLWidget::glDraw()
-{
- Q_D(QGLWidget);
- if (!isValid())
- return;
- if (!d->makeCurrent())
- return;
-#ifndef QT_OPENGL_ES
- if (d->glcx->deviceIsPixmap() && !d->glcx->contextHandle()->isOpenGLES())
- qgl1_functions()->glDrawBuffer(GL_FRONT);
-#endif
- QSize readback_target_size = d->glcx->d_ptr->readback_target_size;
- if (!d->glcx->initialized()) {
- glInit();
- const qreal scaleFactor = (window() && window()->windowHandle()) ?
- window()->windowHandle()->devicePixelRatio() : 1.0;
- int w, h;
- if (readback_target_size.isEmpty()) {
- w = d->glcx->device()->width() * scaleFactor;
- h = d->glcx->device()->height() * scaleFactor;
- } else {
- w = readback_target_size.width();
- h = readback_target_size.height();
- }
- resizeGL(w, h); // New context needs this "resize"
- }
- paintGL();
- if (doubleBuffer() && readback_target_size.isEmpty()) {
- if (d->autoSwap)
- swapBuffers();
- } else {
- qgl_functions()->glFlush();
- }
-}
-
-/*!
- Convenience function for specifying a drawing color to OpenGL.
- Calls glColor4 (in RGBA mode) or glIndex (in color-index mode)
- with the color \a c. Applies to this widgets GL context.
-
- \note This function is not supported on OpenGL/ES 2.0 systems.
-
- \sa qglClearColor(), QGLContext::currentContext(), QColor
-*/
-
-void QGLWidget::qglColor(const QColor& c) const
-{
-#if !defined(QT_OPENGL_ES_2)
-#ifdef QT_OPENGL_ES
- qgl_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
-#else
- Q_D(const QGLWidget);
- const QGLContext *ctx = QGLContext::currentContext();
- if (ctx && !ctx->contextHandle()->isOpenGLES()) {
- if (ctx->format().rgba())
- qgl1_functions()->glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF());
- else if (!d->cmap.isEmpty()) { // QGLColormap in use?
- int i = d->cmap.find(c.rgb());
- if (i < 0)
- i = d->cmap.findNearest(c.rgb());
- qgl1_functions()->glIndexi(i);
- } else
- qgl1_functions()->glIndexi(ctx->colorIndex(c));
- }
-#endif //QT_OPENGL_ES
-#else
- Q_UNUSED(c);
-#endif //QT_OPENGL_ES_2
-}
-
-/*!
- Convenience function for specifying the clearing color to OpenGL.
- Calls glClearColor (in RGBA mode) or glClearIndex (in color-index
- mode) with the color \a c. Applies to this widgets GL context.
-
- \sa qglColor(), QGLContext::currentContext(), QColor
-*/
-
-void QGLWidget::qglClearColor(const QColor& c) const
-{
-#ifdef QT_OPENGL_ES
- qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
-#else
- Q_D(const QGLWidget);
- const QGLContext *ctx = QGLContext::currentContext();
- if (ctx && !ctx->contextHandle()->isOpenGLES()) {
- if (ctx->format().rgba())
- qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
- else if (!d->cmap.isEmpty()) { // QGLColormap in use?
- int i = d->cmap.find(c.rgb());
- if (i < 0)
- i = d->cmap.findNearest(c.rgb());
- qgl1_functions()->glClearIndex(i);
- } else {
- qgl1_functions()->glClearIndex(ctx->colorIndex(c));
- }
- } else {
- qgl_functions()->glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
- }
-#endif
-}
-
-
-/*!
- Converts the image \a img into the unnamed format expected by
- OpenGL functions such as glTexImage2D(). The returned image is not
- usable as a QImage, but QImage::width(), QImage::height() and
- QImage::bits() may be used with OpenGL. The GL format used is
- \c GL_RGBA.
-
- \omit ###
-
- \l opengl/texture example
- The following few lines are from the texture example. Most of the
- code is irrelevant, so we just quote the relevant bits:
-
- \quotefromfile opengl/texture/gltexobj.cpp
- \skipto tex1
- \printline tex1
- \printline gllogo.bmp
-
- We create \e tex1 (and another variable) for OpenGL, and load a real
- image into \e buf.
-
- \skipto convertToGLFormat
- \printline convertToGLFormat
-
- A few lines later, we convert \e buf into OpenGL format and store it
- in \e tex1.
-
- \skipto glTexImage2D
- \printline glTexImage2D
- \printline tex1.bits
-
- Note the dimension restrictions for texture images as described in
- the glTexImage2D() documentation. The width must be 2^m + 2*border
- and the height 2^n + 2*border where m and n are integers and
- border is either 0 or 1.
-
- Another function in the same example uses \e tex1 with OpenGL.
-
- \endomit
-*/
-
-QImage QGLWidget::convertToGLFormat(const QImage& img)
-{
- QImage res(img.size(), QImage::Format_ARGB32);
- convertToGLFormatHelper(res, img.convertToFormat(QImage::Format_ARGB32), GL_RGBA);
- return res;
-}
-
-
-/*!
- \fn QGLColormap & QGLWidget::colormap() const
-
- Returns the colormap for this widget.
-
- Usually it is only top-level widgets that can have different
- colormaps installed. Asking for the colormap of a child widget
- will return the colormap for the child's top-level widget.
-
- If no colormap has been set for this widget, the QGLColormap
- returned will be empty.
-
- \sa setColormap(), QGLColormap::isEmpty()
-*/
-const QGLColormap & QGLWidget::colormap() const
-{
- Q_D(const QGLWidget);
- return d->cmap;
-}
-
-/*!
- \fn void QGLWidget::setColormap(const QGLColormap & cmap)
-
- Set the colormap for this widget to \a cmap. Usually it is only
- top-level widgets that can have colormaps installed.
-
- \sa colormap()
-*/
-void QGLWidget::setColormap(const QGLColormap & c)
-{
- Q_UNUSED(c);
-}
-
-#ifndef QT_OPENGL_ES
-
-static void qt_save_gl_state()
-{
- QOpenGLFunctions *funcs = qgl_functions();
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
-
- gl1funcs->glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
- gl1funcs->glPushAttrib(GL_ALL_ATTRIB_BITS);
- gl1funcs->glMatrixMode(GL_TEXTURE);
- gl1funcs->glPushMatrix();
- gl1funcs->glLoadIdentity();
- gl1funcs->glMatrixMode(GL_PROJECTION);
- gl1funcs->glPushMatrix();
- gl1funcs->glMatrixMode(GL_MODELVIEW);
- gl1funcs->glPushMatrix();
-
- gl1funcs->glShadeModel(GL_FLAT);
- funcs->glDisable(GL_CULL_FACE);
- funcs->glDisable(GL_LIGHTING);
- funcs->glDisable(GL_STENCIL_TEST);
- funcs->glDisable(GL_DEPTH_TEST);
- funcs->glEnable(GL_BLEND);
- funcs->glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
-}
-
-static void qt_restore_gl_state()
-{
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
-
- gl1funcs->glMatrixMode(GL_TEXTURE);
- gl1funcs->glPopMatrix();
- gl1funcs->glMatrixMode(GL_PROJECTION);
- gl1funcs->glPopMatrix();
- gl1funcs->glMatrixMode(GL_MODELVIEW);
- gl1funcs->glPopMatrix();
- gl1funcs->glPopAttrib();
- gl1funcs->glPopClientAttrib();
-}
-
-static void qt_gl_draw_text(QPainter *p, int x, int y, const QString &str,
- const QFont &font)
-{
- GLfloat color[4];
- qgl_functions()->glGetFloatv(GL_CURRENT_COLOR, &color[0]);
-
- QColor col;
- col.setRgbF(color[0], color[1], color[2],color[3]);
- QPen old_pen = p->pen();
- QFont old_font = p->font();
-
- p->setPen(col);
- p->setFont(font);
- p->drawText(x, y, str);
-
- p->setPen(old_pen);
- p->setFont(old_font);
-}
-
-#endif // !QT_OPENGL_ES
-
-/*!
- Renders the string \a str into the GL context of this widget.
-
- \a x and \a y are specified in window coordinates, with the origin
- in the upper left-hand corner of the window. If \a font is not
- specified, the currently set application font will be used to
- render the string. To change the color of the rendered text you can
- use the glColor() call (or the qglColor() convenience function),
- just before the renderText() call.
-
- \note This function clears the stencil buffer.
-
- \note This function is not supported on OpenGL/ES systems.
-
- \note This function temporarily disables depth-testing when the
- text is drawn.
-
- \note This function can only be used inside a
- QPainter::beginNativePainting()/QPainter::endNativePainting() block
- if a painter is active on the QGLWidget.
-*/
-
-void QGLWidget::renderText(int x, int y, const QString &str, const QFont &font)
-{
-#ifndef QT_OPENGL_ES
- Q_D(QGLWidget);
- if (!d->glcx->contextHandle()->isOpenGLES()) {
- Q_D(QGLWidget);
- if (str.isEmpty() || !isValid())
- return;
-
- QOpenGLFunctions *funcs = qgl_functions();
- GLint view[4];
- bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST);
- if (!use_scissor_testing)
- funcs->glGetIntegerv(GL_VIEWPORT, &view[0]);
- int width = d->glcx->device()->width();
- int height = d->glcx->device()->height();
- bool auto_swap = autoBufferSwap();
-
- QPaintEngine *engine = paintEngine();
-
- qt_save_gl_state();
-
- QPainter *p;
- bool reuse_painter = false;
- if (engine->isActive()) {
- reuse_painter = true;
- p = engine->painter();
-
- funcs->glDisable(GL_DEPTH_TEST);
- funcs->glViewport(0, 0, width, height);
- } else {
- setAutoBufferSwap(false);
- // disable glClear() as a result of QPainter::begin()
- d->disable_clear_on_painter_begin = true;
- p = new QPainter(this);
- }
-
- QRect viewport(view[0], view[1], view[2], view[3]);
- if (!use_scissor_testing && viewport != rect()) {
- // if the user hasn't set a scissor box, we set one that
- // covers the current viewport
- funcs->glScissor(view[0], view[1], view[2], view[3]);
- funcs->glEnable(GL_SCISSOR_TEST);
- } else if (use_scissor_testing) {
- // use the scissor box set by the user
- funcs->glEnable(GL_SCISSOR_TEST);
- }
-
- qt_gl_draw_text(p, x, y, str, font);
-
- if (!reuse_painter) {
- p->end();
- delete p;
- setAutoBufferSwap(auto_swap);
- d->disable_clear_on_painter_begin = false;
- }
-
- qt_restore_gl_state();
-
- return;
- }
-#else // QT_OPENGL_ES
- Q_UNUSED(x);
- Q_UNUSED(y);
- Q_UNUSED(str);
- Q_UNUSED(font);
-#endif
- qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
-}
-
-/*! \overload
-
- \a x, \a y and \a z are specified in scene or object coordinates
- relative to the currently set projection and model matrices. This
- can be useful if you want to annotate models with text labels and
- have the labels move with the model as it is rotated etc.
-
- \note This function is not supported on OpenGL/ES systems.
-
- \note If depth testing is enabled before this function is called,
- then the drawn text will be depth-tested against the models that
- have already been drawn in the scene. Use \c{glDisable(GL_DEPTH_TEST)}
- before calling this function to annotate the models without
- depth-testing the text.
-
- \note This function can only be used inside a
- QPainter::beginNativePainting()/QPainter::endNativePainting() block
- if a painter is active on the QGLWidget.
-*/
-void QGLWidget::renderText(double x, double y, double z, const QString &str, const QFont &font)
-{
-#ifndef QT_OPENGL_ES
- Q_D(QGLWidget);
- if (!d->glcx->contextHandle()->isOpenGLES()) {
- Q_D(QGLWidget);
- if (str.isEmpty() || !isValid())
- return;
-
- QOpenGLFunctions *funcs = qgl_functions();
- bool auto_swap = autoBufferSwap();
-
- int width = d->glcx->device()->width();
- int height = d->glcx->device()->height();
- GLdouble model[4 * 4], proj[4 * 4];
- GLint view[4];
- QOpenGLFunctions_1_1 *gl1funcs = qgl1_functions();
- gl1funcs->glGetDoublev(GL_MODELVIEW_MATRIX, &model[0]);
- gl1funcs->glGetDoublev(GL_PROJECTION_MATRIX, &proj[0]);
- funcs->glGetIntegerv(GL_VIEWPORT, &view[0]);
- GLdouble win_x = 0, win_y = 0, win_z = 0;
- qgluProject(x, y, z, &model[0], &proj[0], &view[0],
- &win_x, &win_y, &win_z);
- const int dpr = d->glcx->device()->devicePixelRatioF();
- win_x /= dpr;
- win_y /= dpr;
- win_y = height - win_y; // y is inverted
-
- QPaintEngine *engine = paintEngine();
-
- QPainter *p;
- bool reuse_painter = false;
- bool use_depth_testing = funcs->glIsEnabled(GL_DEPTH_TEST);
- bool use_scissor_testing = funcs->glIsEnabled(GL_SCISSOR_TEST);
-
- qt_save_gl_state();
-
- if (engine->isActive()) {
- reuse_painter = true;
- p = engine->painter();
- } else {
- setAutoBufferSwap(false);
- // disable glClear() as a result of QPainter::begin()
- d->disable_clear_on_painter_begin = true;
- p = new QPainter(this);
- }
-
- QRect viewport(view[0], view[1], view[2], view[3]);
- if (!use_scissor_testing && viewport != rect()) {
- funcs->glScissor(view[0], view[1], view[2], view[3]);
- funcs->glEnable(GL_SCISSOR_TEST);
- } else if (use_scissor_testing) {
- funcs->glEnable(GL_SCISSOR_TEST);
- }
- funcs->glViewport(0, 0, width * dpr, height * dpr);
- gl1funcs->glAlphaFunc(GL_GREATER, 0.0);
- funcs->glEnable(GL_ALPHA_TEST);
- if (use_depth_testing)
- funcs->glEnable(GL_DEPTH_TEST);
-
- // The only option in Qt 5 is the shader-based OpenGL 2 paint engine.
- // Setting fixed pipeline transformations is futile. Instead, pass the
- // extra values directly and let the engine figure the matrices out.
- static_cast<QGL2PaintEngineEx *>(p->paintEngine())->setTranslateZ(-2 * win_z);
-
- qt_gl_draw_text(p, qRound(win_x), qRound(win_y), str, font);
-
- static_cast<QGL2PaintEngineEx *>(p->paintEngine())->setTranslateZ(0);
-
- if (!reuse_painter) {
- p->end();
- delete p;
- setAutoBufferSwap(auto_swap);
- d->disable_clear_on_painter_begin = false;
- }
-
- qt_restore_gl_state();
-
- return;
- }
-#else // QT_OPENGL_ES
- Q_UNUSED(x);
- Q_UNUSED(y);
- Q_UNUSED(z);
- Q_UNUSED(str);
- Q_UNUSED(font);
-#endif
- qWarning("QGLWidget::renderText is not supported under OpenGL/ES");
-}
-
-QGLFormat QGLWidget::format() const
-{
- Q_D(const QGLWidget);
- return d->glcx->format();
-}
-
-QGLContext *QGLWidget::context() const
-{
- Q_D(const QGLWidget);
- return d->glcx;
-}
-
-bool QGLWidget::doubleBuffer() const
-{
- Q_D(const QGLWidget);
- return d->glcx->d_ptr->glFormat.testOption(QGL::DoubleBuffer);
-}
-
-void QGLWidget::setAutoBufferSwap(bool on)
-{
- Q_D(QGLWidget);
- d->autoSwap = on;
-}
-
-bool QGLWidget::autoBufferSwap() const
-{
- Q_D(const QGLWidget);
- return d->autoSwap;
-}
-
-/*!
- Calls QGLContext:::bindTexture(\a image, \a target, \a format) on the currently
- set context.
-
- \sa deleteTexture()
-*/
-GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format)
-{
- if (image.isNull())
- return 0;
-
- Q_D(QGLWidget);
- return d->glcx->bindTexture(image, target, format, QGLContext::DefaultBindOption);
-}
-
-/*!
- \overload
- \since 4.6
-
- The binding \a options are a set of options used to decide how to
- bind the texture to the context.
- */
-GLuint QGLWidget::bindTexture(const QImage &image, GLenum target, GLint format, QGLContext::BindOptions options)
-{
- if (image.isNull())
- return 0;
-
- Q_D(QGLWidget);
- return d->glcx->bindTexture(image, target, format, options);
-}
-
-
-/*!
- Calls QGLContext:::bindTexture(\a pixmap, \a target, \a format) on the currently
- set context.
-
- \sa deleteTexture()
-*/
-GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
-{
- if (pixmap.isNull())
- return 0;
-
- Q_D(QGLWidget);
- return d->glcx->bindTexture(pixmap, target, format, QGLContext::DefaultBindOption);
-}
-
-/*!
- \overload
- \since 4.6
-
- Generates and binds a 2D GL texture to the current context, based
- on \a pixmap. The generated texture id is returned and can be used in
-
- The binding \a options are a set of options used to decide how to
- bind the texture to the context.
- */
-GLuint QGLWidget::bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
- QGLContext::BindOptions options)
-{
- Q_D(QGLWidget);
- return d->glcx->bindTexture(pixmap, target, format, options);
-}
-
-/*! \overload
-
- Calls QGLContext::bindTexture(\a fileName) on the currently set context.
-
- \sa deleteTexture()
-*/
-GLuint QGLWidget::bindTexture(const QString &fileName)
-{
- Q_D(QGLWidget);
- return d->glcx->bindTexture(fileName);
-}
-
-/*!
- Calls QGLContext::deleteTexture(\a id) on the currently set
- context.
-
- \sa bindTexture()
-*/
-void QGLWidget::deleteTexture(GLuint id)
-{
- Q_D(QGLWidget);
- d->glcx->deleteTexture(id);
-}
-
-/*!
- \since 4.4
-
- Calls the corresponding QGLContext::drawTexture() with
- \a target, \a textureId, and \a textureTarget for this
- widget's context.
-*/
-void QGLWidget::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
-{
- Q_D(QGLWidget);
- d->glcx->drawTexture(target, textureId, textureTarget);
-}
-
-/*!
- \since 4.4
-
- Calls the corresponding QGLContext::drawTexture() with
- \a point, \a textureId, and \a textureTarget for this
- widget's context.
-*/
-void QGLWidget::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
-{
- Q_D(QGLWidget);
- d->glcx->drawTexture(point, textureId, textureTarget);
-}
-
-Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_gl_2_engine)
-
-Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
-{
- return qt_gl_2_engine()->engine();
-}
-
-/*!
- \internal
-
- Returns the GL widget's paint engine.
-*/
-QPaintEngine *QGLWidget::paintEngine() const
-{
- return qt_qgl_paint_engine();
-}
-
-void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget)
-{
- Q_Q(QGLWidget);
- q->setAttribute(Qt::WA_PaintOnScreen);
- q->setAttribute(Qt::WA_NoSystemBackground);
- q->setAutoFillBackground(true); // for compatibility
-
- mustHaveWindowHandle = 1;
- q->setAttribute(Qt::WA_NativeWindow);
- q->setWindowFlag(Qt::MSWindowsOwnDC);
-
- initContext(context, shareWidget);
-}
-
-/*
- This is the shared initialization for all platforms. Called from QGLWidgetPrivate::init()
-*/
-void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWidget)
-{
- Q_Q(QGLWidget);
-
- glDevice.setWidget(q);
-
- glcx = 0;
- autoSwap = true;
-
- if (context && !context->device())
- context->setDevice(q);
- q->setContext(context, shareWidget ? shareWidget->context() : 0);
-
- if (!glcx)
- glcx = new QGLContext(QGLFormat::defaultFormat(), q);
-}
-
-bool QGLWidgetPrivate::renderCxPm(QPixmap*)
-{
- return false;
-}
-
-/*! \internal
- Free up any allocated colormaps. This fn is only called for
- top-level widgets.
-*/
-void QGLWidgetPrivate::cleanupColormaps()
-{
-}
-
-void QGLContextGroup::addShare(const QGLContext *context, const QGLContext *share) {
- Q_ASSERT(context && share);
- if (context->d_ptr->group == share->d_ptr->group)
- return;
-
- // Make sure 'context' is not already shared with another group of contexts.
- Q_ASSERT(context->d_ptr->group->m_refs.loadRelaxed() == 1);
-
- // Free 'context' group resources and make it use the same resources as 'share'.
- QGLContextGroup *group = share->d_ptr->group;
- delete context->d_ptr->group;
- context->d_ptr->group = group;
- group->m_refs.ref();
-
- // Maintain a list of all the contexts in each group of sharing contexts.
- // The list is empty if the "share" context wasn't sharing already.
- if (group->m_shares.isEmpty())
- group->m_shares.append(share);
- group->m_shares.append(context);
-}
-
-void QGLContextGroup::removeShare(const QGLContext *context) {
- // Remove the context from the group.
- QGLContextGroup *group = context->d_ptr->group;
- if (group->m_shares.isEmpty())
- return;
- group->m_shares.removeAll(context);
-
- // Update context group representative.
- Q_ASSERT(group->m_shares.size() != 0);
- if (group->m_context == context)
- group->m_context = group->m_shares.at(0);
-
- // If there is only one context left, then make the list empty.
- if (group->m_shares.size() == 1)
- group->m_shares.clear();
-}
-
-QSize QGLTexture::bindCompressedTexture
- (const QString& fileName, const char *format)
-{
- QFile file(fileName);
- if (!file.open(QIODevice::ReadOnly))
- return QSize();
- QByteArray contents = file.readAll();
- file.close();
- return bindCompressedTexture
- (contents.constData(), contents.size(), format);
-}
-
-// PVR header format for container files that store textures compressed
-// with the ETC1, PVRTC2, and PVRTC4 encodings. Format information from the
-// PowerVR SDK at http://www.imgtec.com/powervr/insider/powervr-sdk.asp
-// "PVRTexTool Reference Manual, version 1.11f".
-struct PvrHeader
-{
- quint32 headerSize;
- quint32 height;
- quint32 width;
- quint32 mipMapCount;
- quint32 flags;
- quint32 dataSize;
- quint32 bitsPerPixel;
- quint32 redMask;
- quint32 greenMask;
- quint32 blueMask;
- quint32 alphaMask;
- quint32 magic;
- quint32 surfaceCount;
-};
-
-#define PVR_MAGIC 0x21525650 // "PVR!" in little-endian
-
-#define PVR_FORMAT_MASK 0x000000FF
-#define PVR_FORMAT_PVRTC2 0x00000018
-#define PVR_FORMAT_PVRTC4 0x00000019
-#define PVR_FORMAT_ETC1 0x00000036
-
-#define PVR_HAS_MIPMAPS 0x00000100
-#define PVR_TWIDDLED 0x00000200
-#define PVR_NORMAL_MAP 0x00000400
-#define PVR_BORDER_ADDED 0x00000800
-#define PVR_CUBE_MAP 0x00001000
-#define PVR_FALSE_COLOR_MIPMAPS 0x00002000
-#define PVR_VOLUME_TEXTURE 0x00004000
-#define PVR_ALPHA_IN_TEXTURE 0x00008000
-#define PVR_VERTICAL_FLIP 0x00010000
-
-#ifndef GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG
-#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00
-#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01
-#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02
-#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03
-#endif
-
-#ifndef GL_ETC1_RGB8_OES
-#define GL_ETC1_RGB8_OES 0x8D64
-#endif
-
-bool QGLTexture::canBindCompressedTexture
- (const char *buf, int len, const char *format, bool *hasAlpha)
-{
- if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
- // Compressed texture loading only supported on little-endian
- // systems such as x86 and ARM at the moment.
- return false;
- }
- if (!format) {
- // Auto-detect the format from the header.
- if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
- *hasAlpha = true;
- return true;
- } else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
- const PvrHeader *pvrHeader =
- reinterpret_cast<const PvrHeader *>(buf);
- *hasAlpha = (pvrHeader->alphaMask != 0);
- return true;
- }
- } else {
- // Validate the format against the header.
- if (!qstricmp(format, "DDS")) {
- if (len >= 4 && !qstrncmp(buf, "DDS ", 4)) {
- *hasAlpha = true;
- return true;
- }
- } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
- if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4)) {
- const PvrHeader *pvrHeader =
- reinterpret_cast<const PvrHeader *>(buf);
- *hasAlpha = (pvrHeader->alphaMask != 0);
- return true;
- }
- }
- }
- return false;
-}
-
-#define ctx QGLContext::currentContext()
-
-QSize QGLTexture::bindCompressedTexture
- (const char *buf, int len, const char *format)
-{
- if (QSysInfo::ByteOrder != QSysInfo::LittleEndian) {
- // Compressed texture loading only supported on little-endian
- // systems such as x86 and ARM at the moment.
- return QSize();
- }
- if (!format) {
- // Auto-detect the format from the header.
- if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
- return bindCompressedTextureDDS(buf, len);
- else if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
- return bindCompressedTexturePVR(buf, len);
- } else {
- // Validate the format against the header.
- if (!qstricmp(format, "DDS")) {
- if (len >= 4 && !qstrncmp(buf, "DDS ", 4))
- return bindCompressedTextureDDS(buf, len);
- } else if (!qstricmp(format, "PVR") || !qstricmp(format, "ETC1")) {
- if (len >= 52 && !qstrncmp(buf + 44, "PVR!", 4))
- return bindCompressedTexturePVR(buf, len);
- }
- }
- return QSize();
-}
-
-QSize QGLTexture::bindCompressedTextureDDS(const char *buf, int len)
-{
- // We only support 2D texture loading at present.
- if (target != GL_TEXTURE_2D)
- return QSize();
-
- // Bail out if the necessary extension is not present.
- if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::DDSTextureCompression)) {
- qWarning("QGLContext::bindTexture(): DDS texture compression is not supported.");
- return QSize();
- }
-
- const DDSFormat *ddsHeader = reinterpret_cast<const DDSFormat *>(buf + 4);
- if (!ddsHeader->dwLinearSize) {
- qWarning("QGLContext::bindTexture(): DDS image size is not valid.");
- return QSize();
- }
-
- int blockSize = 16;
- GLenum format;
-
- switch(ddsHeader->ddsPixelFormat.dwFourCC) {
- case FOURCC_DXT1:
- format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
- blockSize = 8;
- break;
- case FOURCC_DXT3:
- format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
- break;
- case FOURCC_DXT5:
- format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- break;
- default:
- qWarning("QGLContext::bindTexture(): DDS image format not supported.");
- return QSize();
- }
-
- const GLubyte *pixels =
- reinterpret_cast<const GLubyte *>(buf + ddsHeader->dwSize + 4);
-
- QOpenGLFunctions *funcs = qgl_functions();
- funcs->glGenTextures(1, &id);
- funcs->glBindTexture(GL_TEXTURE_2D, id);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
- int size;
- int offset = 0;
- int available = len - int(ddsHeader->dwSize + 4);
- int w = ddsHeader->dwWidth;
- int h = ddsHeader->dwHeight;
-
- // load mip-maps
- for(int i = 0; i < (int) ddsHeader->dwMipMapCount; ++i) {
- if (w == 0) w = 1;
- if (h == 0) h = 1;
-
- size = ((w+3)/4) * ((h+3)/4) * blockSize;
- if (size > available)
- break;
- qgl_extensions()->glCompressedTexImage2D(GL_TEXTURE_2D, i, format, w, h, 0,
- size, pixels + offset);
- offset += size;
- available -= size;
-
- // half size for each mip-map level
- w = w/2;
- h = h/2;
- }
-
- // DDS images are not inverted.
- options &= ~QGLContext::InvertedYBindOption;
-
- return QSize(ddsHeader->dwWidth, ddsHeader->dwHeight);
-}
-
-QSize QGLTexture::bindCompressedTexturePVR(const char *buf, int len)
-{
- // We only support 2D texture loading at present. Cube maps later.
- if (target != GL_TEXTURE_2D)
- return QSize();
-
- // Determine which texture format we will be loading.
- const PvrHeader *pvrHeader = reinterpret_cast<const PvrHeader *>(buf);
- GLenum textureFormat;
- quint32 minWidth, minHeight;
- switch (pvrHeader->flags & PVR_FORMAT_MASK) {
- case PVR_FORMAT_PVRTC2:
- if (pvrHeader->alphaMask)
- textureFormat = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
- else
- textureFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
- minWidth = 16;
- minHeight = 8;
- break;
-
- case PVR_FORMAT_PVRTC4:
- if (pvrHeader->alphaMask)
- textureFormat = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
- else
- textureFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
- minWidth = 8;
- minHeight = 8;
- break;
-
- case PVR_FORMAT_ETC1:
- textureFormat = GL_ETC1_RGB8_OES;
- minWidth = 4;
- minHeight = 4;
- break;
-
- default:
- qWarning("QGLContext::bindTexture(): PVR image format 0x%x not supported.", int(pvrHeader->flags & PVR_FORMAT_MASK));
- return QSize();
- }
-
- // Bail out if the necessary extension is not present.
- if (textureFormat == GL_ETC1_RGB8_OES) {
- if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::ETC1TextureCompression)) {
- qWarning("QGLContext::bindTexture(): ETC1 texture compression is not supported.");
- return QSize();
- }
- } else {
- if (!qgl_extensions()->hasOpenGLExtension(QOpenGLExtensions::PVRTCTextureCompression)) {
- qWarning("QGLContext::bindTexture(): PVRTC texture compression is not supported.");
- return QSize();
- }
- }
-
- // Boundary check on the buffer size.
- quint32 bufferSize = pvrHeader->headerSize + pvrHeader->dataSize;
- if (bufferSize > quint32(len)) {
- qWarning("QGLContext::bindTexture(): PVR image size is not valid.");
- return QSize();
- }
-
- // Create the texture.
- QOpenGLFunctions *funcs = qgl_functions();
- funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- funcs->glGenTextures(1, &id);
- funcs->glBindTexture(GL_TEXTURE_2D, id);
- if (pvrHeader->mipMapCount) {
- if ((options & QGLContext::LinearFilteringBindOption) != 0) {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
- } else {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
- }
- } else if ((options & QGLContext::LinearFilteringBindOption) != 0) {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- } else {
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- }
-
- // Load the compressed mipmap levels.
- const GLubyte *buffer =
- reinterpret_cast<const GLubyte *>(buf + pvrHeader->headerSize);
- bufferSize = pvrHeader->dataSize;
- quint32 level = 0;
- quint32 width = pvrHeader->width;
- quint32 height = pvrHeader->height;
- while (bufferSize > 0 && level <= pvrHeader->mipMapCount) {
- quint32 size =
- (qMax(width, minWidth) * qMax(height, minHeight) *
- pvrHeader->bitsPerPixel) / 8;
- if (size > bufferSize)
- break;
- qgl_extensions()->glCompressedTexImage2D(GL_TEXTURE_2D, GLint(level), textureFormat,
- GLsizei(width), GLsizei(height), 0,
- GLsizei(size), buffer);
- width /= 2;
- height /= 2;
- buffer += size;
- ++level;
- }
-
- // Restore the default pixel alignment for later texture uploads.
- funcs->glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
- // Set the invert flag for the texture. The "vertical flip"
- // flag in PVR is the opposite sense to our sense of inversion.
- options.setFlag(QGLContext::InvertedYBindOption, !(pvrHeader->flags & PVR_VERTICAL_FLIP));
-
- return QSize(pvrHeader->width, pvrHeader->height);
-}
-
-#undef ctx
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
deleted file mode 100644
index f5accbeb3c..0000000000
--- a/src/opengl/qgl.h
+++ /dev/null
@@ -1,524 +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_H
-#define QGL_H
-
-#ifndef QT_NO_OPENGL
-
-#include <QtGui/qopengl.h>
-#include <QtWidgets/qwidget.h>
-#include <QtGui/qpaintengine.h>
-#include <QtOpenGL/qglcolormap.h>
-#include <QtCore/qmap.h>
-#include <QtCore/qscopedpointer.h>
-
-#include <QtGui/QSurfaceFormat>
-
-QT_BEGIN_NAMESPACE
-
-
-
-
-class QPixmap;
-class QGLWidgetPrivate;
-class QGLContextPrivate;
-
-// Namespace class:
-namespace QGL
-{
- enum FormatOption {
- DoubleBuffer = 0x0001,
- DepthBuffer = 0x0002,
- Rgba = 0x0004,
- AlphaChannel = 0x0008,
- AccumBuffer = 0x0010,
- StencilBuffer = 0x0020,
- StereoBuffers = 0x0040,
- DirectRendering = 0x0080,
- HasOverlay = 0x0100,
- SampleBuffers = 0x0200,
- DeprecatedFunctions = 0x0400,
- SingleBuffer = DoubleBuffer << 16,
- NoDepthBuffer = DepthBuffer << 16,
- ColorIndex = Rgba << 16,
- NoAlphaChannel = AlphaChannel << 16,
- NoAccumBuffer = AccumBuffer << 16,
- NoStencilBuffer = StencilBuffer << 16,
- NoStereoBuffers = StereoBuffers << 16,
- IndirectRendering = DirectRendering << 16,
- NoOverlay = HasOverlay << 16,
- NoSampleBuffers = SampleBuffers << 16,
- NoDeprecatedFunctions = DeprecatedFunctions << 16
- };
- Q_DECLARE_FLAGS(FormatOptions, FormatOption)
-}
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGL::FormatOptions)
-
-class QGLFormatPrivate;
-
-class Q_OPENGL_EXPORT QGLFormat
-{
-public:
- QGLFormat();
- QGLFormat(QGL::FormatOptions options, int plane = 0);
- QGLFormat(const QGLFormat &other);
- QGLFormat &operator=(const QGLFormat &other);
- ~QGLFormat();
-
- void setDepthBufferSize(int size);
- int depthBufferSize() const;
-
- void setAccumBufferSize(int size);
- int accumBufferSize() const;
-
- void setRedBufferSize(int size);
- int redBufferSize() const;
-
- void setGreenBufferSize(int size);
- int greenBufferSize() const;
-
- void setBlueBufferSize(int size);
- int blueBufferSize() const;
-
- void setAlphaBufferSize(int size);
- int alphaBufferSize() const;
-
- void setStencilBufferSize(int size);
- int stencilBufferSize() const;
-
- void setSampleBuffers(bool enable);
- bool sampleBuffers() const;
-
- void setSamples(int numSamples);
- int samples() const;
-
- void setSwapInterval(int interval);
- int swapInterval() const;
-
- bool doubleBuffer() const;
- void setDoubleBuffer(bool enable);
- bool depth() const;
- void setDepth(bool enable);
- bool rgba() const;
- void setRgba(bool enable);
- bool alpha() const;
- void setAlpha(bool enable);
- bool accum() const;
- void setAccum(bool enable);
- bool stencil() const;
- void setStencil(bool enable);
- bool stereo() const;
- void setStereo(bool enable);
- bool directRendering() const;
- void setDirectRendering(bool enable);
- bool hasOverlay() const;
- void setOverlay(bool enable);
-
- int plane() const;
- void setPlane(int plane);
-
- void setOption(QGL::FormatOptions opt);
- bool testOption(QGL::FormatOptions opt) const;
-
- static QGLFormat defaultFormat();
- static void setDefaultFormat(const QGLFormat& f);
-
- static QGLFormat defaultOverlayFormat();
- static void setDefaultOverlayFormat(const QGLFormat& f);
-
- static bool hasOpenGL();
- static bool hasOpenGLOverlays();
-
- void setVersion(int major, int minor);
- int majorVersion() const;
- int minorVersion() const;
-
- enum OpenGLContextProfile {
- NoProfile,
- CoreProfile,
- CompatibilityProfile
- };
-
- void setProfile(OpenGLContextProfile profile);
- OpenGLContextProfile profile() const;
-
- enum OpenGLVersionFlag {
- OpenGL_Version_None = 0x00000000,
- OpenGL_Version_1_1 = 0x00000001,
- OpenGL_Version_1_2 = 0x00000002,
- OpenGL_Version_1_3 = 0x00000004,
- OpenGL_Version_1_4 = 0x00000008,
- OpenGL_Version_1_5 = 0x00000010,
- OpenGL_Version_2_0 = 0x00000020,
- OpenGL_Version_2_1 = 0x00000040,
- OpenGL_ES_Common_Version_1_0 = 0x00000080,
- OpenGL_ES_CommonLite_Version_1_0 = 0x00000100,
- OpenGL_ES_Common_Version_1_1 = 0x00000200,
- OpenGL_ES_CommonLite_Version_1_1 = 0x00000400,
- OpenGL_ES_Version_2_0 = 0x00000800,
- OpenGL_Version_3_0 = 0x00001000,
- OpenGL_Version_3_1 = 0x00002000,
- OpenGL_Version_3_2 = 0x00004000,
- OpenGL_Version_3_3 = 0x00008000,
- OpenGL_Version_4_0 = 0x00010000,
- OpenGL_Version_4_1 = 0x00020000,
- OpenGL_Version_4_2 = 0x00040000,
- OpenGL_Version_4_3 = 0x00080000
- };
- Q_DECLARE_FLAGS(OpenGLVersionFlags, OpenGLVersionFlag)
-
- static OpenGLVersionFlags openGLVersionFlags();
-
- static QGLFormat fromSurfaceFormat(const QSurfaceFormat &format);
- static QSurfaceFormat toSurfaceFormat(const QGLFormat &format);
-private:
- QGLFormatPrivate *d;
-
- void detach();
-
- friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
- friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
-#ifndef QT_NO_DEBUG_STREAM
- friend Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
-#endif
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFormat::OpenGLVersionFlags)
-
-Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
-Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
-
-#ifndef QT_NO_DEBUG_STREAM
-Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
-#endif
-
-class QGLFunctions;
-
-class Q_OPENGL_EXPORT QGLContext
-{
- Q_DECLARE_PRIVATE(QGLContext)
-public:
- QGLContext(const QGLFormat& format, QPaintDevice* device);
- QGLContext(const QGLFormat& format);
- virtual ~QGLContext();
-
- virtual bool create(const QGLContext* shareContext = nullptr);
- bool isValid() const;
- bool isSharing() const;
- void reset();
-
- static bool areSharing(const QGLContext *context1, const QGLContext *context2);
-
- QGLFormat format() const;
- QGLFormat requestedFormat() const;
- void setFormat(const QGLFormat& format);
-
- void moveToThread(QThread *thread);
-
- virtual void makeCurrent();
- virtual void doneCurrent();
-
- virtual void swapBuffers() const;
-
- QGLFunctions *functions() const;
-
- enum BindOption {
- NoBindOption = 0x0000,
- InvertedYBindOption = 0x0001,
- MipmapBindOption = 0x0002,
- PremultipliedAlphaBindOption = 0x0004,
- LinearFilteringBindOption = 0x0008,
-
- MemoryManagedBindOption = 0x0010, // internal flag
- CanFlipNativePixmapBindOption = 0x0020, // internal flag
- TemporarilyCachedBindOption = 0x0040, // internal flag
-
- DefaultBindOption = LinearFilteringBindOption
- | InvertedYBindOption
- | MipmapBindOption,
- InternalBindOption = MemoryManagedBindOption
- | PremultipliedAlphaBindOption
- };
- Q_DECLARE_FLAGS(BindOptions, BindOption)
-
- GLuint bindTexture(const QImage &image, GLenum target, GLint format,
- BindOptions options);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
- BindOptions options);
-
- GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
- GLint format = GL_RGBA);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
- GLint format = GL_RGBA);
- GLuint bindTexture(const QString &fileName);
-
- void deleteTexture(GLuint tx_id);
-
- void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
- void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-
- static void setTextureCacheLimit(int size);
- static int textureCacheLimit();
-
- QFunctionPointer getProcAddress(const QString &proc) const;
- QPaintDevice* device() const;
- QColor overlayTransparentColor() const;
-
- static const QGLContext* currentContext();
-
- static QGLContext *fromOpenGLContext(QOpenGLContext *platformContext);
- QOpenGLContext *contextHandle() const;
-
-protected:
- virtual bool chooseContext(const QGLContext* shareContext = nullptr);
-
- bool deviceIsPixmap() const;
- bool windowCreated() const;
- void setWindowCreated(bool on);
- bool initialized() const;
- void setInitialized(bool on);
-
- uint colorIndex(const QColor& c) const;
- void setValid(bool valid);
- void setDevice(QPaintDevice *pDev);
-
-protected:
- static QGLContext* currentCtx;
-
-private:
- QGLContext(QOpenGLContext *windowContext);
-
- QScopedPointer<QGLContextPrivate> d_ptr;
-
- friend class QGLPixelBuffer;
- friend class QGLPixelBufferPrivate;
- friend class QGLWidget;
- friend class QGLWidgetPrivate;
- friend class QGLGlyphCache;
- friend class QGL2PaintEngineEx;
- friend class QGL2PaintEngineExPrivate;
- friend class QGLEngineShaderManager;
- friend class QGLTextureGlyphCache;
- friend struct QGLGlyphTexture;
- friend class QGLContextGroup;
- friend class QGLPixmapBlurFilter;
- friend class QGLTexture;
- friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
- friend class QGLFramebufferObject;
- friend class QGLFramebufferObjectPrivate;
- friend class QGLFBOGLPaintDevice;
- friend class QGLPaintDevice;
- friend class QGLWidgetGLPaintDevice;
- friend class QX11GLSharedContexts;
- friend class QGLContextResourceBase;
- friend class QSGDistanceFieldGlyphCache;
-private:
- Q_DISABLE_COPY(QGLContext)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGLContext::BindOptions)
-
-class Q_OPENGL_EXPORT QGLWidget : public QWidget
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QGLWidget)
-public:
- explicit QGLWidget(QWidget* parent=nullptr,
- const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f=Qt::WindowFlags());
- explicit QGLWidget(QGLContext *context, QWidget* parent=nullptr,
- const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f=Qt::WindowFlags());
- explicit QGLWidget(const QGLFormat& format, QWidget* parent=nullptr,
- const QGLWidget* shareWidget = nullptr, Qt::WindowFlags f=Qt::WindowFlags());
- ~QGLWidget();
-
- void qglColor(const QColor& c) const;
- void qglClearColor(const QColor& c) const;
-
- bool isValid() const;
- bool isSharing() const;
-
- void makeCurrent();
- void doneCurrent();
-
- bool doubleBuffer() const;
- void swapBuffers();
-
- QGLFormat format() const;
- void setFormat(const QGLFormat& format);
-
- QGLContext* context() const;
- void setContext(QGLContext* context, const QGLContext* shareContext = nullptr,
- bool deleteOldContext = true);
-
- QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
- QImage grabFrameBuffer(bool withAlpha = false);
-
- void makeOverlayCurrent();
- const QGLContext* overlayContext() const;
-
- static QImage convertToGLFormat(const QImage& img);
-
- const QGLColormap & colormap() const;
- void setColormap(const QGLColormap & map);
-
- void renderText(int x, int y, const QString & str,
- const QFont & fnt = QFont());
- void renderText(double x, double y, double z, const QString & str,
- const QFont & fnt = QFont());
- QPaintEngine *paintEngine() const override;
-
- GLuint bindTexture(const QImage &image, GLenum target, GLint format,
- QGLContext::BindOptions options);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
- QGLContext::BindOptions options);
-
- GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
- GLint format = GL_RGBA);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
- GLint format = GL_RGBA);
-
- GLuint bindTexture(const QString &fileName);
-
- void deleteTexture(GLuint tx_id);
-
- void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
- void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-
-public Q_SLOTS:
- virtual void updateGL();
- virtual void updateOverlayGL();
-
-protected:
- bool event(QEvent *) override;
- virtual void initializeGL();
- virtual void resizeGL(int w, int h);
- virtual void paintGL();
-
- virtual void initializeOverlayGL();
- virtual void resizeOverlayGL(int w, int h);
- virtual void paintOverlayGL();
-
- void setAutoBufferSwap(bool on);
- bool autoBufferSwap() const;
-
- void paintEvent(QPaintEvent*) override;
- void resizeEvent(QResizeEvent*) override;
-
- virtual void glInit();
- virtual void glDraw();
-
- QGLWidget(QGLWidgetPrivate &dd,
- const QGLFormat &format = QGLFormat(),
- QWidget *parent = nullptr,
- const QGLWidget* shareWidget = nullptr,
- Qt::WindowFlags f = Qt::WindowFlags());
-private:
- Q_DISABLE_COPY(QGLWidget)
-
- friend class QGLDrawable;
- friend class QGLPixelBuffer;
- friend class QGLPixelBufferPrivate;
- friend class QGLContext;
- friend class QGLContextPrivate;
- friend class QGLOverlayWidget;
- friend class QGLPaintDevice;
- friend class QGLWidgetGLPaintDevice;
-};
-
-
-//
-// QGLFormat inline functions
-//
-
-inline bool QGLFormat::doubleBuffer() const
-{
- return testOption(QGL::DoubleBuffer);
-}
-
-inline bool QGLFormat::depth() const
-{
- return testOption(QGL::DepthBuffer);
-}
-
-inline bool QGLFormat::rgba() const
-{
- return testOption(QGL::Rgba);
-}
-
-inline bool QGLFormat::alpha() const
-{
- return testOption(QGL::AlphaChannel);
-}
-
-inline bool QGLFormat::accum() const
-{
- return testOption(QGL::AccumBuffer);
-}
-
-inline bool QGLFormat::stencil() const
-{
- return testOption(QGL::StencilBuffer);
-}
-
-inline bool QGLFormat::stereo() const
-{
- return testOption(QGL::StereoBuffers);
-}
-
-inline bool QGLFormat::directRendering() const
-{
- return testOption(QGL::DirectRendering);
-}
-
-inline bool QGLFormat::hasOverlay() const
-{
- return testOption(QGL::HasOverlay);
-}
-
-inline bool QGLFormat::sampleBuffers() const
-{
- return testOption(QGL::SampleBuffers);
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_OPENGL
-#endif // QGL_H
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
deleted file mode 100644
index 4e52c0f5e9..0000000000
--- a/src/opengl/qgl_p.h
+++ /dev/null
@@ -1,556 +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_P_H
-#define QGL_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the QGLWidget class. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "QtOpenGL/qgl.h"
-#include "QtOpenGL/qglcolormap.h"
-#include "QtCore/qmap.h"
-#include "QtCore/qthread.h"
-#include "QtCore/qthreadstorage.h"
-#include "QtCore/qhashfunctions.h"
-#include "QtCore/qatomic.h"
-#include "QtWidgets/private/qwidget_p.h"
-#include "QtGui/private/qopenglcontext_p.h"
-#include "QtGui/private/qopenglextensions_p.h"
-#include "qcache.h"
-#include "qglpaintdevice_p.h"
-
-#include <QtGui/QOpenGLContext>
-
-QT_BEGIN_NAMESPACE
-
-class QGLContext;
-class QGLOverlayWidget;
-class QPixmap;
-class QOpenGLExtensions;
-
-class QGLFormatPrivate
-{
-public:
- QGLFormatPrivate()
- : ref(1)
- {
- opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering
- | QGL::StencilBuffer | QGL::DeprecatedFunctions;
- pln = 0;
- depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
- numSamples = -1;
- swapInterval = -1;
- majorVersion = 2;
- minorVersion = 0;
- profile = QGLFormat::NoProfile;
- }
- QGLFormatPrivate(const QGLFormatPrivate *other)
- : ref(1),
- opts(other->opts),
- pln(other->pln),
- depthSize(other->depthSize),
- accumSize(other->accumSize),
- stencilSize(other->stencilSize),
- redSize(other->redSize),
- greenSize(other->greenSize),
- blueSize(other->blueSize),
- alphaSize(other->alphaSize),
- numSamples(other->numSamples),
- swapInterval(other->swapInterval),
- majorVersion(other->majorVersion),
- minorVersion(other->minorVersion),
- profile(other->profile)
- {
- }
- QAtomicInt ref;
- QGL::FormatOptions opts;
- int pln;
- int depthSize;
- int accumSize;
- int stencilSize;
- int redSize;
- int greenSize;
- int blueSize;
- int alphaSize;
- int numSamples;
- int swapInterval;
- int majorVersion;
- int minorVersion;
- QGLFormat::OpenGLContextProfile profile;
-};
-
-class Q_OPENGL_EXPORT QGLWidgetPrivate : public QWidgetPrivate
-{
- Q_DECLARE_PUBLIC(QGLWidget)
-public:
- QGLWidgetPrivate() : QWidgetPrivate()
- , disable_clear_on_painter_begin(false)
- , parent_changing(false)
- {
- }
-
- ~QGLWidgetPrivate() {}
-
- void init(QGLContext *context, const QGLWidget* shareWidget);
- void initContext(QGLContext *context, const QGLWidget* shareWidget);
- bool renderCxPm(QPixmap *pixmap);
- void cleanupColormaps();
- void aboutToDestroy() override {
- if (glcx && !parent_changing)
- glcx->reset();
- }
-
- bool makeCurrent();
-
- QGLContext *glcx;
- QGLWidgetGLPaintDevice glDevice;
- bool autoSwap;
-
- QGLColormap cmap;
-
- bool disable_clear_on_painter_begin;
- bool parent_changing;
-};
-
-// QGLContextPrivate has the responsibility of creating context groups.
-// QGLContextPrivate maintains the reference counter and destroys
-// context groups when needed.
-class QGLContextGroup
-{
-public:
- ~QGLContextGroup();
-
- const QGLContext *context() const {return m_context;}
- bool isSharing() const { return m_shares.size() >= 2; }
- QList<const QGLContext *> shares() const { return m_shares; }
-
- static void addShare(const QGLContext *context, const QGLContext *share);
- static void removeShare(const QGLContext *context);
-
-private:
- QGLContextGroup(const QGLContext *context);
-
- const QGLContext *m_context; // context group's representative
- QList<const QGLContext *> m_shares;
- QAtomicInt m_refs;
-
- friend class QGLContext;
- friend class QGLContextPrivate;
- friend class QGLContextGroupResourceBase;
-};
-
-// Get the context that resources for "ctx" will transfer to once
-// "ctx" is destroyed. Returns null if nothing is sharing with ctx.
-const QGLContext *qt_gl_transfer_context(const QGLContext *);
-
-/*
- QGLTemporaryContext - the main objective of this class is to have a way of
- creating a GL context and making it current, without going via QGLWidget
- and friends. At certain points during GL initialization we need a current
- context in order decide what GL features are available, and to resolve GL
- extensions. Having a light-weight way of creating such a context saves
- initial application startup time, and it doesn't wind up creating recursive
- conflicts.
- The class currently uses a private d pointer to hide the platform specific
- types. This could possibly been done inline with #ifdef'ery, but it causes
- major headaches on e.g. X11 due to namespace pollution.
-*/
-class QGLTemporaryContextPrivate;
-class QGLTemporaryContext {
-public:
- explicit QGLTemporaryContext(bool directRendering = true, QWidget *parent = nullptr);
- ~QGLTemporaryContext();
-
-private:
- QScopedPointer<QGLTemporaryContextPrivate> d;
-};
-
-class QGLTexture;
-class QGLTextureDestroyer;
-
-// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
-// all the GL2 engine uses:
-#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
-
-class QGLContextResourceBase;
-
-class QGLContextPrivate
-{
- Q_DECLARE_PUBLIC(QGLContext)
-public:
- explicit QGLContextPrivate(QGLContext *context);
- ~QGLContextPrivate();
- QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
- QGLContext::BindOptions options);
- QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
- QGLContext::BindOptions options);
- QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
- QGLContext::BindOptions options);
- QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
- void init(QPaintDevice *dev, const QGLFormat &format);
- int maxTextureSize();
-
- void cleanup();
-
- void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
- void syncGlState(); // Makes sure the GL context's state is what we think it is
- void swapRegion(const QRegion &region);
-
- QOpenGLContext *guiGlContext;
- // true if QGLContext owns the QOpenGLContext (for who deletes who)
- bool ownContext;
-
- void setupSharing();
- void refreshCurrentFbo();
- void setCurrentFbo(GLuint fbo);
-
- QGLFormat glFormat;
- QGLFormat reqFormat;
- GLuint fbo;
-
- uint valid : 1;
- uint sharing : 1;
- uint initDone : 1;
- uint crWin : 1;
- uint internal_context : 1;
- uint version_flags_cached : 1;
-
- // workarounds for driver/hw bugs on different platforms
- uint workaround_needsFullClearOnEveryFrame : 1;
- uint workaround_brokenFBOReadBack : 1;
- uint workaround_brokenTexSubImage : 1;
- uint workaroundsCached : 1;
-
- uint workaround_brokenTextureFromPixmap : 1;
- uint workaround_brokenTextureFromPixmap_init : 1;
-
- uint workaround_brokenAlphaTexSubImage : 1;
- uint workaround_brokenAlphaTexSubImage_init : 1;
-
- QPaintDevice *paintDevice;
- QSize readback_target_size;
- QColor transpColor;
- QGLContext *q_ptr;
- QGLFormat::OpenGLVersionFlags version_flags;
-
- QGLContextGroup *group;
- GLint max_texture_size;
-
- GLuint current_fbo;
- GLuint default_fbo;
- QPaintEngine *active_engine;
- QGLTextureDestroyer *texture_destroyer;
-
- QGLFunctions *functions;
-
- bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
-
- static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
-
- static void setCurrentContext(QGLContext *context);
-};
-
-// Temporarily make a context current if not already current or
-// shared with the current contex. The previous context is made
-// current when the object goes out of scope.
-class Q_OPENGL_EXPORT QGLShareContextScope
-{
-public:
- QGLShareContextScope(const QGLContext *ctx)
- : m_oldContext(nullptr)
- {
- QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
- if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
- m_oldContext = currentContext;
- m_ctx = const_cast<QGLContext *>(ctx);
- m_ctx->makeCurrent();
- } else {
- m_ctx = currentContext;
- }
- }
-
- operator QGLContext *()
- {
- return m_ctx;
- }
-
- QGLContext *operator->()
- {
- return m_ctx;
- }
-
- ~QGLShareContextScope()
- {
- if (m_oldContext)
- m_oldContext->makeCurrent();
- }
-
-private:
- QGLContext *m_oldContext;
- QGLContext *m_ctx;
-};
-
-QT_END_NAMESPACE
-Q_DECLARE_METATYPE(GLuint)
-QT_BEGIN_NAMESPACE
-
-class Q_OPENGL_EXPORT QGLTextureDestroyer
-{
-public:
- void emitFreeTexture(QGLContext *context, QPlatformPixmap *, GLuint id) {
- if (context->contextHandle())
- (new QOpenGLSharedResourceGuard(context->contextHandle(), id, freeTextureFunc))->free();
- }
-
-private:
- static void freeTextureFunc(QOpenGLFunctions *, GLuint id) {
- QOpenGLContext::currentContext()->functions()->glDeleteTextures(1, &id);
- }
-};
-
-class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
-{
- Q_OBJECT
-public:
- void emitAboutToDestroyContext(const QGLContext *context) {
- emit aboutToDestroyContext(context);
- }
- static QGLSignalProxy *instance();
-Q_SIGNALS:
- void aboutToDestroyContext(const QGLContext *context);
-};
-
-class QGLTexture {
-public:
- explicit QGLTexture(QGLContext *ctx = nullptr, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
- QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
- : context(ctx),
- id(tx_id),
- target(tx_target),
- options(opt)
- {}
-
- ~QGLTexture() {
- if (options & QGLContext::MemoryManagedBindOption) {
- Q_ASSERT(context);
- QPlatformPixmap *boundPixmap = nullptr;
- context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id);
- }
- }
-
- QGLContext *context;
- GLuint id;
- GLenum target;
-
- QGLContext::BindOptions options;
-
- bool canBindCompressedTexture
- (const char *buf, int len, const char *format, bool *hasAlpha);
- QSize bindCompressedTexture
- (const QString& fileName, const char *format = nullptr);
- QSize bindCompressedTexture
- (const char *buf, int len, const char *format = nullptr);
- QSize bindCompressedTextureDDS(const char *buf, int len);
- QSize bindCompressedTexturePVR(const char *buf, int len);
-};
-
-struct QGLTextureCacheKey {
- qint64 key;
- QGLContextGroup *group;
-};
-
-inline bool operator==(const QGLTextureCacheKey &a, const QGLTextureCacheKey &b)
-{
- return a.key == b.key && a.group == b.group;
-}
-
-inline uint qHash(const QGLTextureCacheKey &key)
-{
- return qHash(key.key) ^ qHash(key.group);
-}
-
-
-class Q_AUTOTEST_EXPORT QGLTextureCache {
-public:
- QGLTextureCache();
- ~QGLTextureCache();
-
- void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
- void remove(qint64 key);
- inline int size();
- inline void setMaxCost(int newMax);
- inline int maxCost();
- inline QGLTexture* getTexture(QGLContext *ctx, qint64 key);
-
- bool remove(QGLContext *ctx, GLuint textureId);
- void removeContextTextures(QGLContext *ctx);
- static QGLTextureCache *instance();
- static void cleanupTexturesForCacheKey(qint64 cacheKey);
- static void cleanupTexturesForPixampData(QPlatformPixmap* pixmap);
- static void cleanupBeforePixmapDestruction(QPlatformPixmap* pixmap);
-
-private:
- QCache<QGLTextureCacheKey, QGLTexture> m_cache;
- QReadWriteLock m_lock;
-};
-
-int QGLTextureCache::size() {
- QReadLocker locker(&m_lock);
- return m_cache.size();
-}
-
-void QGLTextureCache::setMaxCost(int newMax)
-{
- QWriteLocker locker(&m_lock);
- m_cache.setMaxCost(newMax);
-}
-
-int QGLTextureCache::maxCost()
-{
- QReadLocker locker(&m_lock);
- return m_cache.maxCost();
-}
-
-QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key)
-{
- // Can't be a QReadLocker since QCache::object() modifies the cache (reprioritizes the object)
- QWriteLocker locker(&m_lock);
- const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
- return m_cache.object(cacheKey);
-}
-
-Q_OPENGL_EXPORT extern QPaintEngine* qt_qgl_paint_engine();
-
-QOpenGLExtensions* qgl_extensions();
-bool qgl_hasFeature(QOpenGLFunctions::OpenGLFeature feature);
-bool qgl_hasExtension(QOpenGLExtensions::OpenGLExtension extension);
-
-// Put a guard around a GL object identifier and its context.
-// When the context goes away, a shared context will be used
-// in its place. If there are no more shared contexts, then
-// the identifier is returned as zero - it is assumed that the
-// context destruction cleaned up the identifier in this case.
-class QGLSharedResourceGuardBase : public QOpenGLSharedResource
-{
-public:
- QGLSharedResourceGuardBase(QGLContext *context, GLuint id)
- : QOpenGLSharedResource(context->contextHandle()->shareGroup())
- , m_id(id)
- {
- }
-
- GLuint id() const
- {
- return m_id;
- }
-
-protected:
- void invalidateResource() override
- {
- m_id = 0;
- }
-
- void freeResource(QOpenGLContext *context) override
- {
- if (m_id) {
- freeResource(QGLContext::fromOpenGLContext(context), m_id);
- }
- }
-
- virtual void freeResource(QGLContext *ctx, GLuint id) = 0;
-
-private:
- GLuint m_id;
-};
-
-template <typename Func>
-class QGLSharedResourceGuard : public QGLSharedResourceGuardBase
-{
-public:
- QGLSharedResourceGuard(QGLContext *context, GLuint id, Func func)
- : QGLSharedResourceGuardBase(context, id)
- , m_func(func)
- {
- }
-
-protected:
- void freeResource(QGLContext *ctx, GLuint id) override
- {
- m_func(ctx, id);
- }
-
-private:
- Func m_func;
-};
-
-template <typename Func>
-QGLSharedResourceGuardBase *createSharedResourceGuard(QGLContext *context, GLuint id, Func cleanupFunc)
-{
- return new QGLSharedResourceGuard<Func>(context, id, cleanupFunc);
-}
-
-// this is a class that wraps a QThreadStorage object for storing
-// thread local instances of the GL 1 and GL 2 paint engines
-
-template <class T>
-class QGLEngineThreadStorage
-{
-public:
- QPaintEngine *engine() {
- QPaintEngine *&localEngine = storage.localData();
- if (!localEngine)
- localEngine = new T;
- return localEngine;
- }
-
-private:
- QThreadStorage<QPaintEngine *> storage;
-};
-QT_END_NAMESPACE
-
-#endif // QGL_P_H
diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp
deleted file mode 100644
index bb9c2affbd..0000000000
--- a/src/opengl/qglbuffer.cpp
+++ /dev/null
@@ -1,568 +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 <QtOpenGL/qgl.h>
-#include <QtOpenGL/private/qgl_p.h>
-#include <private/qopenglextensions_p.h>
-#include <QtCore/qatomic.h>
-#include "qglbuffer.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QGLBuffer
- \inmodule QtOpenGL
- \brief The QGLBuffer class provides functions for creating and managing GL buffer objects.
- \since 4.7
- \obsolete
- \ingroup painting-3D
-
- Buffer objects are created in the GL server so that the
- client application can avoid uploading vertices, indices,
- texture image data, etc every time they are needed.
-
- QGLBuffer objects can be copied around as a reference to the
- underlying GL buffer object:
-
- \snippet code/src_opengl_qglbuffer.cpp 0
-
- QGLBuffer performs a shallow copy when objects are copied in this
- manner, but does not implement copy-on-write semantics. The original
- object will be affected whenever the copy is modified.
-
- \note This class has been deprecated in favor of QOpenGLBuffer.
-*/
-
-/*!
- \enum QGLBuffer::Type
- This enum defines the type of GL buffer object to create with QGLBuffer.
-
- \value VertexBuffer Vertex buffer object for use when specifying
- vertex arrays.
- \value IndexBuffer Index buffer object for use with \c{glDrawElements()}.
- \value PixelPackBuffer Pixel pack buffer object for reading pixel
- data from the GL server (for example, with \c{glReadPixels()}).
- Not supported under OpenGL/ES.
- \value PixelUnpackBuffer Pixel unpack buffer object for writing pixel
- data to the GL server (for example, with \c{glTexImage2D()}).
- Not supported under OpenGL/ES.
-*/
-
-/*!
- \enum QGLBuffer::UsagePattern
- This enum defines the usage pattern of a QGLBuffer object.
-
- \value StreamDraw The data will be set once and used a few times
- for drawing operations. Under OpenGL/ES 1.1 this is identical
- to StaticDraw.
- \value StreamRead The data will be set once and used a few times
- for reading data back from the GL server. Not supported
- under OpenGL/ES.
- \value StreamCopy The data will be set once and used a few times
- for reading data back from the GL server for use in further
- drawing operations. Not supported under OpenGL/ES.
- \value StaticDraw The data will be set once and used many times
- for drawing operations.
- \value StaticRead The data will be set once and used many times
- for reading data back from the GL server. Not supported
- under OpenGL/ES.
- \value StaticCopy The data will be set once and used many times
- for reading data back from the GL server for use in further
- drawing operations. Not supported under OpenGL/ES.
- \value DynamicDraw The data will be modified repeatedly and used
- many times for drawing operations.
- \value DynamicRead The data will be modified repeatedly and used
- many times for reading data back from the GL server.
- Not supported under OpenGL/ES.
- \value DynamicCopy The data will be modified repeatedly and used
- many times for reading data back from the GL server for
- use in further drawing operations. Not supported under OpenGL/ES.
-*/
-
-/*!
- \enum QGLBuffer::Access
- This enum defines the access mode for QGLBuffer::map().
-
- \value ReadOnly The buffer will be mapped for reading only.
- \value WriteOnly The buffer will be mapped for writing only.
- \value ReadWrite The buffer will be mapped for reading and writing.
-*/
-
-class QGLBufferPrivate
-{
-public:
- QGLBufferPrivate(QGLBuffer::Type t)
- : ref(1),
- type(t),
- guard(0),
- usagePattern(QGLBuffer::StaticDraw),
- actualUsagePattern(QGLBuffer::StaticDraw),
- funcs(0)
- {
- }
-
- QAtomicInt ref;
- QGLBuffer::Type type;
- QGLSharedResourceGuardBase *guard;
- QGLBuffer::UsagePattern usagePattern;
- QGLBuffer::UsagePattern actualUsagePattern;
- QOpenGLExtensions *funcs;
-};
-
-/*!
- Constructs a new buffer object of type QGLBuffer::VertexBuffer.
-
- Note: this constructor just creates the QGLBuffer instance. The actual
- buffer object in the GL server is not created until create() is called.
-
- \sa create()
-*/
-QGLBuffer::QGLBuffer()
- : d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer))
-{
-}
-
-/*!
- Constructs a new buffer object of \a type.
-
- Note: this constructor just creates the QGLBuffer instance. The actual
- buffer object in the GL server is not created until create() is called.
-
- \sa create()
-*/
-QGLBuffer::QGLBuffer(QGLBuffer::Type type)
- : d_ptr(new QGLBufferPrivate(type))
-{
-}
-
-/*!
- Constructs a shallow copy of \a other.
-
- Note: QGLBuffer does not implement copy-on-write semantics,
- so \a other will be affected whenever the copy is modified.
-*/
-QGLBuffer::QGLBuffer(const QGLBuffer &other)
- : d_ptr(other.d_ptr)
-{
- d_ptr->ref.ref();
-}
-
-#define ctx QGLContext::currentContext();
-
-/*!
- Destroys this buffer object, including the storage being
- used in the GL server.
-*/
-QGLBuffer::~QGLBuffer()
-{
- if (!d_ptr->ref.deref()) {
- destroy();
- delete d_ptr;
- }
-}
-
-/*!
- Assigns a shallow copy of \a other to this object.
-
- Note: QGLBuffer does not implement copy-on-write semantics,
- so \a other will be affected whenever the copy is modified.
-*/
-QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other)
-{
- if (d_ptr != other.d_ptr) {
- other.d_ptr->ref.ref();
- if (!d_ptr->ref.deref()) {
- destroy();
- delete d_ptr;
- }
- d_ptr = other.d_ptr;
- }
- return *this;
-}
-
-/*!
- Returns the type of buffer represented by this object.
-*/
-QGLBuffer::Type QGLBuffer::type() const
-{
- Q_D(const QGLBuffer);
- return d->type;
-}
-
-/*!
- Returns the usage pattern for this buffer object.
- The default value is StaticDraw.
-
- \sa setUsagePattern()
-*/
-QGLBuffer::UsagePattern QGLBuffer::usagePattern() const
-{
- Q_D(const QGLBuffer);
- return d->usagePattern;
-}
-
-/*!
- Sets the usage pattern for this buffer object to \a value.
- This function must be called before allocate() or write().
-
- \sa usagePattern(), allocate(), write()
-*/
-void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value)
-{
- Q_D(QGLBuffer);
- d->usagePattern = d->actualUsagePattern = value;
-}
-
-#undef ctx
-
-namespace {
- void freeBufferFunc(QGLContext *ctx, GLuint id)
- {
- Q_ASSERT(ctx);
- ctx->contextHandle()->functions()->glDeleteBuffers(1, &id);
- }
-}
-
-/*!
- Creates the buffer object in the GL server. Returns \c true if
- the object was created; false otherwise.
-
- This function must be called with a current QGLContext.
- The buffer will be bound to and can only be used in
- that context (or any other context that is shared with it).
-
- This function will return false if the GL implementation
- does not support buffers, or there is no current QGLContext.
-
- \sa isCreated(), allocate(), write(), destroy()
-*/
-bool QGLBuffer::create()
-{
- Q_D(QGLBuffer);
- if (d->guard && d->guard->id())
- return true;
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
- if (ctx) {
- delete d->funcs;
- d->funcs = new QOpenGLExtensions(ctx->contextHandle());
- if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers))
- return false;
-
- GLuint bufferId = 0;
- d->funcs->glGenBuffers(1, &bufferId);
- if (bufferId) {
- if (d->guard)
- d->guard->free();
-
- d->guard = createSharedResourceGuard(ctx, bufferId, freeBufferFunc);
- return true;
- }
- }
- return false;
-}
-
-#define ctx QGLContext::currentContext()
-
-/*!
- Returns \c true if this buffer has been created; false otherwise.
-
- \sa create(), destroy()
-*/
-bool QGLBuffer::isCreated() const
-{
- Q_D(const QGLBuffer);
- return d->guard && d->guard->id();
-}
-
-/*!
- Destroys this buffer object, including the storage being
- used in the GL server. All references to the buffer will
- become invalid.
-*/
-void QGLBuffer::destroy()
-{
- Q_D(QGLBuffer);
- if (d->guard) {
- d->guard->free();
- d->guard = 0;
- }
-}
-
-/*!
- Reads the \a count bytes in this buffer starting at \a offset
- into \a data. Returns \c true on success; false if reading from
- the buffer is not supported. Buffer reading is not supported
- under OpenGL/ES.
-
- It is assumed that this buffer has been bound to the current context.
-
- \sa write(), bind()
-*/
-bool QGLBuffer::read(int offset, void *data, int count)
-{
-#if !defined(QT_OPENGL_ES)
- Q_D(QGLBuffer);
- if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id() || !d->funcs->d()->GetBufferSubData)
- return false;
- while (d->funcs->glGetError() != GL_NO_ERROR) ; // Clear error state.
- d->funcs->glGetBufferSubData(d->type, offset, count, data);
- return d->funcs->glGetError() == GL_NO_ERROR;
-#else
- Q_UNUSED(offset);
- Q_UNUSED(data);
- Q_UNUSED(count);
- return false;
-#endif
-}
-
-/*!
- Replaces the \a count bytes of this buffer starting at \a offset
- with the contents of \a data. Any other bytes in the buffer
- will be left unmodified.
-
- It is assumed that create() has been called on this buffer and that
- it has been bound to the current context.
-
- \sa create(), read(), allocate()
-*/
-void QGLBuffer::write(int offset, const void *data, int count)
-{
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::allocate(): buffer not created");
-#endif
- Q_D(QGLBuffer);
- if (d->guard && d->guard->id())
- d->funcs->glBufferSubData(d->type, offset, count, data);
-}
-
-/*!
- Allocates \a count bytes of space to the buffer, initialized to
- the contents of \a data. Any previous contents will be removed.
-
- It is assumed that create() has been called on this buffer and that
- it has been bound to the current context.
-
- \sa create(), read(), write()
-*/
-void QGLBuffer::allocate(const void *data, int count)
-{
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::allocate(): buffer not created");
-#endif
- Q_D(QGLBuffer);
- if (d->guard && d->guard->id())
- d->funcs->glBufferData(d->type, count, data, d->actualUsagePattern);
-}
-
-/*!
- \fn void QGLBuffer::allocate(int count)
- \overload
-
- Allocates \a count bytes of space to the buffer. Any previous
- contents will be removed.
-
- It is assumed that create() has been called on this buffer and that
- it has been bound to the current context.
-
- \sa create(), write()
-*/
-
-/*!
- Binds the buffer associated with this object to the current
- GL context. Returns \c false if binding was not possible, usually because
- type() is not supported on this GL implementation.
-
- The buffer must be bound to the same QGLContext current when create()
- was called, or to another QGLContext that is sharing with it.
- Otherwise, false will be returned from this function.
-
- \sa release(), create()
-*/
-bool QGLBuffer::bind()
-{
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::bind(): buffer not created");
-#endif
- Q_D(const QGLBuffer);
- GLuint bufferId = d->guard ? d->guard->id() : 0;
- if (bufferId) {
- if (d->guard->group() != QOpenGLContextGroup::currentContextGroup()) {
-#ifndef QT_NO_DEBUG
- qWarning("QGLBuffer::bind: buffer is not valid in the current context");
-#endif
- return false;
- }
- d->funcs->glBindBuffer(d->type, bufferId);
- return true;
- } else {
- return false;
- }
-}
-
-/*!
- Releases the buffer associated with this object from the
- current GL context.
-
- This function must be called with the same QGLContext current
- as when bind() was called on the buffer.
-
- \sa bind()
-*/
-void QGLBuffer::release()
-{
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::release(): buffer not created");
-#endif
- Q_D(const QGLBuffer);
- if (d->guard && d->guard->id())
- d->funcs->glBindBuffer(d->type, 0);
-}
-
-#undef ctx
-
-/*!
- Releases the buffer associated with \a type in the current
- QGLContext.
-
- This function is a direct call to \c{glBindBuffer(type, 0)}
- for use when the caller does not know which QGLBuffer has
- been bound to the context but wants to make sure that it
- is released.
-
- \snippet code/src_opengl_qglbuffer.cpp 1
-*/
-void QGLBuffer::release(QGLBuffer::Type type)
-{
- if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
- ctx->functions()->glBindBuffer(GLenum(type), 0);
-}
-
-#define ctx QGLContext::currentContext()
-
-/*!
- Returns the GL identifier associated with this buffer; zero if
- the buffer has not been created.
-
- \sa isCreated()
-*/
-GLuint QGLBuffer::bufferId() const
-{
- Q_D(const QGLBuffer);
- return d->guard ? d->guard->id() : 0;
-}
-
-#ifndef GL_BUFFER_SIZE
-#define GL_BUFFER_SIZE 0x8764
-#endif
-
-/*!
- Returns the size of the data in this buffer, for reading operations.
- Returns -1 if fetching the buffer size is not supported, or the
- buffer has not been created.
-
- It is assumed that this buffer has been bound to the current context.
-
- \sa isCreated(), bind()
-*/
-int QGLBuffer::size() const
-{
- Q_D(const QGLBuffer);
- if (!d->guard || !d->guard->id())
- return -1;
- GLint value = -1;
- d->funcs->glGetBufferParameteriv(d->type, GL_BUFFER_SIZE, &value);
- return value;
-}
-
-/*!
- Maps the contents of this buffer into the application's memory
- space and returns a pointer to it. Returns null if memory
- mapping is not possible. The \a access parameter indicates the
- type of access to be performed.
-
- It is assumed that create() has been called on this buffer and that
- it has been bound to the current context.
-
- This function is only supported under OpenGL/ES if the
- \c{GL_OES_mapbuffer} extension is present.
-
- \sa unmap(), create(), bind()
-*/
-void *QGLBuffer::map(QGLBuffer::Access access)
-{
- Q_D(QGLBuffer);
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::map(): buffer not created");
-#endif
- if (!d->guard || !d->guard->id())
- return 0;
- return d->funcs->glMapBuffer(d->type, access);
-}
-
-/*!
- Unmaps the buffer after it was mapped into the application's
- memory space with a previous call to map(). Returns \c true if
- the unmap succeeded; false otherwise.
-
- It is assumed that this buffer has been bound to the current context,
- and that it was previously mapped with map().
-
- This function is only supported under OpenGL/ES if the
- \c{GL_OES_mapbuffer} extension is present.
-
- \sa map()
-*/
-bool QGLBuffer::unmap()
-{
- Q_D(QGLBuffer);
-#ifndef QT_NO_DEBUG
- if (!isCreated())
- qWarning("QGLBuffer::unmap(): buffer not created");
-#endif
- if (!d->guard || !d->guard->id())
- return false;
- return d->funcs->glUnmapBuffer(d->type) == GL_TRUE;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglbuffer.h b/src/opengl/qglbuffer.h
deleted file mode 100644
index daf5227c66..0000000000
--- a/src/opengl/qglbuffer.h
+++ /dev/null
@@ -1,125 +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 QGLBUFFER_H
-#define QGLBUFFER_H
-
-#include <QtCore/qscopedpointer.h>
-#include <QtOpenGL/qgl.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLBufferPrivate;
-
-class Q_OPENGL_EXPORT QGLBuffer
-{
-public:
- enum Type
- {
- VertexBuffer = 0x8892, // GL_ARRAY_BUFFER
- IndexBuffer = 0x8893, // GL_ELEMENT_ARRAY_BUFFER
- PixelPackBuffer = 0x88EB, // GL_PIXEL_PACK_BUFFER
- PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER
- };
-
- QGLBuffer();
- explicit QGLBuffer(QGLBuffer::Type type);
- QGLBuffer(const QGLBuffer &other);
- ~QGLBuffer();
-
- QGLBuffer &operator=(const QGLBuffer &other);
-
- enum UsagePattern
- {
- StreamDraw = 0x88E0, // GL_STREAM_DRAW
- StreamRead = 0x88E1, // GL_STREAM_READ
- StreamCopy = 0x88E2, // GL_STREAM_COPY
- StaticDraw = 0x88E4, // GL_STATIC_DRAW
- StaticRead = 0x88E5, // GL_STATIC_READ
- StaticCopy = 0x88E6, // GL_STATIC_COPY
- DynamicDraw = 0x88E8, // GL_DYNAMIC_DRAW
- DynamicRead = 0x88E9, // GL_DYNAMIC_READ
- DynamicCopy = 0x88EA // GL_DYNAMIC_COPY
- };
-
- enum Access
- {
- ReadOnly = 0x88B8, // GL_READ_ONLY
- WriteOnly = 0x88B9, // GL_WRITE_ONLY
- ReadWrite = 0x88BA // GL_READ_WRITE
- };
-
- QGLBuffer::Type type() const;
-
- QGLBuffer::UsagePattern usagePattern() const;
- void setUsagePattern(QGLBuffer::UsagePattern value);
-
- bool create();
- bool isCreated() const;
-
- void destroy();
-
- bool bind();
- void release();
-
- static void release(QGLBuffer::Type type);
-
- GLuint bufferId() const;
-
- int size() const;
-
- bool read(int offset, void *data, int count);
- void write(int offset, const void *data, int count);
-
- void allocate(const void *data, int count);
- inline void allocate(int count) { allocate(nullptr, count); }
-
- void *map(QGLBuffer::Access access);
- bool unmap();
-
-private:
- QGLBufferPrivate *d_ptr;
-
- Q_DECLARE_PRIVATE(QGLBuffer)
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/opengl/qglcolormap.cpp b/src/opengl/qglcolormap.cpp
deleted file mode 100644
index f314a9715d..0000000000
--- a/src/opengl/qglcolormap.cpp
+++ /dev/null
@@ -1,296 +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$
-**
-****************************************************************************/
-
-/*!
- \class QGLColormap
- \brief The QGLColormap class is used for installing custom colormaps into
- a QGLWidget.
-
- \obsolete
- \inmodule QtOpenGL
- \ingroup painting-3D
- \ingroup shared
-
- QGLColormap provides a platform independent way of specifying and
- installing indexed colormaps for a QGLWidget. QGLColormap is
- especially useful when using the OpenGL color-index mode.
-
- Under X11 you must use an X server that supports either a \c
- PseudoColor or \c DirectColor visual class. If your X server
- currently only provides a \c GrayScale, \c TrueColor, \c
- StaticColor or \c StaticGray visual, you will not be able to
- allocate colorcells for writing. If this is the case, try setting
- your X server to 8 bit mode. It should then provide you with at
- least a \c PseudoColor visual. Note that you may experience
- colormap flashing if your X server is running in 8 bit mode.
-
- The size() of the colormap is always set to 256
- colors. Note that under Windows you can also install colormaps
- in child widgets.
-
- This class uses \l{implicit sharing} as a memory and speed
- optimization.
-
- Example of use:
- \snippet code/src_opengl_qglcolormap.cpp 0
-
- \sa QGLWidget::setColormap(), QGLWidget::colormap()
-*/
-
-/*!
- \fn Qt::HANDLE QGLColormap::handle()
-
- \internal
-
- Returns the handle for this color map.
-*/
-
-/*!
- \fn void QGLColormap::setHandle(Qt::HANDLE handle)
-
- \internal
-
- Sets the handle for this color map to \a handle.
-*/
-
-#include "qglcolormap.h"
-
-QT_BEGIN_NAMESPACE
-
-QGLColormap::QGLColormapData QGLColormap::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
-
-/*!
- Construct a QGLColormap.
-*/
-QGLColormap::QGLColormap()
- : d(&shared_null)
-{
- d->ref.ref();
-}
-
-
-/*!
- Construct a shallow copy of \a map.
-*/
-QGLColormap::QGLColormap(const QGLColormap &map)
- : d(map.d)
-{
- d->ref.ref();
-}
-
-/*!
- Dereferences the QGLColormap and deletes it if this was the last
- reference to it.
-*/
-QGLColormap::~QGLColormap()
-{
- if (!d->ref.deref())
- cleanup(d);
-}
-
-void QGLColormap::cleanup(QGLColormap::QGLColormapData *x)
-{
- delete x->cells;
- x->cells = 0;
- delete x;
-}
-
-/*!
- Assign a shallow copy of \a map to this QGLColormap.
-*/
-QGLColormap & QGLColormap::operator=(const QGLColormap &map)
-{
- map.d->ref.ref();
- if (!d->ref.deref())
- cleanup(d);
- d = map.d;
- return *this;
-}
-
-/*!
- \fn void QGLColormap::detach()
- \internal
-
- Detaches this QGLColormap from the shared block.
-*/
-
-void QGLColormap::detach_helper()
-{
- QGLColormapData *x = new QGLColormapData;
- x->ref.storeRelaxed(1);
- x->cmapHandle = 0;
- x->cells = 0;
- if (d->cells) {
- x->cells = new QVector<QRgb>(256);
- *x->cells = *d->cells;
- }
- if (!d->ref.deref())
- cleanup(d);
- d = x;
-}
-
-/*!
- Set cell at index \a idx in the colormap to color \a color.
-*/
-void QGLColormap::setEntry(int idx, QRgb color)
-{
- detach();
- if (!d->cells)
- d->cells = new QVector<QRgb>(256);
- d->cells->replace(idx, color);
-}
-
-/*!
- Set an array of cells in this colormap. \a count is the number of
- colors that should be set, \a colors is the array of colors, and
- \a base is the starting index. The first element in \a colors
- is set at \a base in the colormap.
-*/
-void QGLColormap::setEntries(int count, const QRgb *colors, int base)
-{
- detach();
- if (!d->cells)
- d->cells = new QVector<QRgb>(256);
-
- Q_ASSERT_X(colors && base >= 0 && (base + count) <= d->cells->size(), "QGLColormap::setEntries",
- "preconditions not met");
- for (int i = 0; i < count; ++i)
- setEntry(base + i, colors[i]);
-}
-
-/*!
- Returns the QRgb value in the colorcell with index \a idx.
-*/
-QRgb QGLColormap::entryRgb(int idx) const
-{
- if (d == &shared_null || !d->cells)
- return 0;
- else
- return d->cells->at(idx);
-}
-
-/*!
- \overload
-
- Set the cell with index \a idx in the colormap to color \a color.
-*/
-void QGLColormap::setEntry(int idx, const QColor &color)
-{
- setEntry(idx, color.rgb());
-}
-
-/*!
- Returns the QRgb value in the colorcell with index \a idx.
-*/
-QColor QGLColormap::entryColor(int idx) const
-{
- if (d == &shared_null || !d->cells)
- return QColor();
- else
- return QColor(d->cells->at(idx));
-}
-
-/*!
- Returns \c true if the colormap is empty or it is not in use
- by a QGLWidget; otherwise returns \c false.
-
- A colormap with no color values set is considered to be empty.
- For historical reasons, a colormap that has color values set
- but which is not in use by a QGLWidget is also considered empty.
-
- Compare size() with zero to determine if the colormap is empty
- regardless of whether it is in use by a QGLWidget or not.
-
- \sa size()
-*/
-bool QGLColormap::isEmpty() const
-{
- return d == &shared_null || d->cells == 0 || d->cells->size() == 0 || d->cmapHandle == 0;
-}
-
-
-/*!
- Returns the number of colorcells in the colormap.
-*/
-int QGLColormap::size() const
-{
- return d->cells ? d->cells->size() : 0;
-}
-
-/*!
- Returns the index of the color \a color. If \a color is not in the
- map, -1 is returned.
-*/
-int QGLColormap::find(QRgb color) const
-{
- if (d->cells)
- return d->cells->indexOf(color);
- return -1;
-}
-
-/*!
- Returns the index of the color that is the closest match to color
- \a color.
-*/
-int QGLColormap::findNearest(QRgb color) const
-{
- int idx = find(color);
- if (idx >= 0)
- return idx;
- int mapSize = size();
- int mindist = 200000;
- int r = qRed(color);
- int g = qGreen(color);
- int b = qBlue(color);
- int rx, gx, bx, dist;
- for (int i = 0; i < mapSize; ++i) {
- QRgb ci = d->cells->at(i);
- rx = r - qRed(ci);
- gx = g - qGreen(ci);
- bx = b - qBlue(ci);
- dist = rx * rx + gx * gx + bx * bx; // calculate distance
- if (dist < mindist) { // minimal?
- mindist = dist;
- idx = i;
- }
- }
- return idx;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
deleted file mode 100644
index 362b3ef189..0000000000
--- a/src/opengl/qglframebufferobject.cpp
+++ /dev/null
@@ -1,1466 +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 "qglframebufferobject.h"
-#include "qglframebufferobject_p.h"
-
-#include <qdebug.h>
-#include <private/qgl_p.h>
-#include <private/qfont_p.h>
-#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
-
-#include <qimage.h>
-#include <qwindow.h>
-
-QT_BEGIN_NAMESPACE
-
-extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
-
-#define QGL_FUNC_CONTEXT const QGLContext *ctx = QGLContext::currentContext();
-#define QGL_FUNCP_CONTEXT const QGLContext *ctx = QGLContext::currentContext();
-
-#ifndef QT_NO_DEBUG
-#define QT_RESET_GLERROR() \
-{ \
- while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \
-}
-#define QT_CHECK_GLERROR() \
-{ \
- GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \
- if (err != GL_NO_ERROR) { \
- qDebug("[%s line %d] GL Error: %d", \
- __FILE__, __LINE__, (int)err); \
- } \
-}
-#else
-#define QT_RESET_GLERROR() {}
-#define QT_CHECK_GLERROR() {}
-#endif
-
-// ####TODO Properly #ifdef this class to use #define symbols actually defined
-// by OpenGL/ES includes
-#ifndef GL_MAX_SAMPLES
-#define GL_MAX_SAMPLES 0x8D57
-#endif
-
-#ifndef GL_RENDERBUFFER_SAMPLES
-#define GL_RENDERBUFFER_SAMPLES 0x8CAB
-#endif
-
-#ifndef GL_DEPTH24_STENCIL8
-#define GL_DEPTH24_STENCIL8 0x88F0
-#endif
-
-#ifndef GL_DEPTH_COMPONENT24
-#define GL_DEPTH_COMPONENT24 0x81A6
-#endif
-
-#ifndef GL_DEPTH_COMPONENT24_OES
-#define GL_DEPTH_COMPONENT24_OES 0x81A6
-#endif
-
-#ifndef GL_READ_FRAMEBUFFER
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#endif
-
-#ifndef GL_DRAW_FRAMEBUFFER
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#endif
-
-#ifndef GL_DEPTH_STENCIL_ATTACHMENT
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#endif
-
-#ifndef GL_DEPTH_STENCIL
-#define GL_DEPTH_STENCIL 0x84F9
-#endif
-
-/*!
- \class QGLFramebufferObjectFormat
- \inmodule QtOpenGL
- \brief The QGLFramebufferObjectFormat class specifies the format of an OpenGL
- framebuffer object.
-
- \since 4.6
- \obsolete
-
- \ingroup painting-3D
-
- A framebuffer object has several characteristics:
- \list
- \li \l{setSamples()}{Number of samples per pixels.}
- \li \l{setAttachment()}{Depth and/or stencil attachments.}
- \li \l{setTextureTarget()}{Texture target.}
- \li \l{setInternalTextureFormat()}{Internal texture format.}
- \endlist
-
- Note that the desired attachments or number of samples per pixels might not
- be supported by the hardware driver. Call QGLFramebufferObject::format()
- after creating a QGLFramebufferObject to find the exact format that was
- used to create the frame buffer object.
-
- \note This class has been deprecated in favor of QOpenGLFramebufferObjectFormat.
-
- \sa QGLFramebufferObject
-*/
-
-/*!
- \internal
-*/
-void QGLFramebufferObjectFormat::detach()
-{
- if (d->ref.loadRelaxed() != 1) {
- QGLFramebufferObjectFormatPrivate *newd
- = new QGLFramebufferObjectFormatPrivate(d);
- if (!d->ref.deref())
- delete d;
- d = newd;
- }
-}
-
-/*!
- Creates a QGLFramebufferObjectFormat object for specifying
- the format of an OpenGL framebuffer object.
-
- By default the format specifies a non-multisample framebuffer object with no
- attachments, texture target \c GL_TEXTURE_2D, and internal format \c GL_RGBA8.
- On OpenGL/ES systems, the default internal format is \c GL_RGBA.
-
- \sa samples(), attachment(), internalTextureFormat()
-*/
-
-QGLFramebufferObjectFormat::QGLFramebufferObjectFormat()
-{
- d = new QGLFramebufferObjectFormatPrivate;
-}
-
-/*!
- Constructs a copy of \a other.
-*/
-
-QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other)
-{
- d = other.d;
- d->ref.ref();
-}
-
-/*!
- Assigns \a other to this object.
-*/
-
-QGLFramebufferObjectFormat &QGLFramebufferObjectFormat::operator=(const QGLFramebufferObjectFormat &other)
-{
- if (d != other.d) {
- other.d->ref.ref();
- if (!d->ref.deref())
- delete d;
- d = other.d;
- }
- return *this;
-}
-
-/*!
- Destroys the QGLFramebufferObjectFormat.
-*/
-QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()
-{
- if (!d->ref.deref())
- delete d;
-}
-
-/*!
- Sets the number of samples per pixel for a multisample framebuffer object
- to \a samples. The default sample count of 0 represents a regular
- non-multisample framebuffer object.
-
- If the desired amount of samples per pixel is not supported by the hardware
- then the maximum number of samples per pixel will be used. Note that
- multisample framebuffer objects cannot be bound as textures. Also, the
- \c{GL_EXT_framebuffer_multisample} extension is required to create a
- framebuffer with more than one sample per pixel.
-
- \sa samples()
-*/
-void QGLFramebufferObjectFormat::setSamples(int samples)
-{
- detach();
- d->samples = samples;
-}
-
-/*!
- Returns the number of samples per pixel if a framebuffer object
- is a multisample framebuffer object. Otherwise, returns 0.
- The default value is 0.
-
- \sa setSamples()
-*/
-int QGLFramebufferObjectFormat::samples() const
-{
- return d->samples;
-}
-
-/*!
- \since 4.8
-
- Enables mipmapping if \a enabled is true; otherwise disables it.
-
- Mipmapping is disabled by default.
-
- If mipmapping is enabled, additional memory will be allocated for
- the mipmap levels. The mipmap levels can be updated by binding the
- texture and calling glGenerateMipmap(). Mipmapping cannot be enabled
- for multisampled framebuffer objects.
-
- \sa mipmap(), QGLFramebufferObject::texture()
-*/
-void QGLFramebufferObjectFormat::setMipmap(bool enabled)
-{
- detach();
- d->mipmap = enabled;
-}
-
-/*!
- \since 4.8
-
- Returns \c true if mipmapping is enabled.
-
- \sa setMipmap()
-*/
-bool QGLFramebufferObjectFormat::mipmap() const
-{
- return d->mipmap;
-}
-
-/*!
- Sets the attachment configuration of a framebuffer object to \a attachment.
-
- \sa attachment()
-*/
-void QGLFramebufferObjectFormat::setAttachment(QGLFramebufferObject::Attachment attachment)
-{
- detach();
- d->attachment = attachment;
-}
-
-/*!
- Returns the configuration of the depth and stencil buffers attached to
- a framebuffer object. The default is QGLFramebufferObject::NoAttachment.
-
- \sa setAttachment()
-*/
-QGLFramebufferObject::Attachment QGLFramebufferObjectFormat::attachment() const
-{
- return d->attachment;
-}
-
-/*!
- Sets the texture target of the texture attached to a framebuffer object to
- \a target. Ignored for multisample framebuffer objects.
-
- \sa textureTarget(), samples()
-*/
-void QGLFramebufferObjectFormat::setTextureTarget(GLenum target)
-{
- detach();
- d->target = target;
-}
-
-/*!
- Returns the texture target of the texture attached to a framebuffer object.
- Ignored for multisample framebuffer objects. The default is
- \c GL_TEXTURE_2D.
-
- \sa setTextureTarget(), samples()
-*/
-GLenum QGLFramebufferObjectFormat::textureTarget() const
-{
- return d->target;
-}
-
-/*!
- Sets the internal format of a framebuffer object's texture or
- multisample framebuffer object's color buffer to
- \a internalTextureFormat.
-
- \sa internalTextureFormat()
-*/
-void QGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat)
-{
- detach();
- d->internal_format = internalTextureFormat;
-}
-
-/*!
- Returns the internal format of a framebuffer object's texture or
- multisample framebuffer object's color buffer. The default is
- \c GL_RGBA8 on desktop OpenGL systems, and \c GL_RGBA on
- OpenGL/ES systems.
-
- \sa setInternalTextureFormat()
-*/
-GLenum QGLFramebufferObjectFormat::internalTextureFormat() const
-{
- return d->internal_format;
-}
-
-/*!
- Returns \c true if all the options of this framebuffer object format
- are the same as \a other; otherwise returns \c false.
-*/
-bool QGLFramebufferObjectFormat::operator==(const QGLFramebufferObjectFormat& other) const
-{
- if (d == other.d)
- return true;
- else
- return d->equals(other.d);
-}
-
-/*!
- Returns \c false if all the options of this framebuffer object format
- are the same as \a other; otherwise returns \c true.
-*/
-bool QGLFramebufferObjectFormat::operator!=(const QGLFramebufferObjectFormat& other) const
-{
- return !(*this == other);
-}
-
-void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f,
- QGLFramebufferObject::Attachment attachment)
-{
- fbo = f;
- m_thisFBO = fbo->d_func()->fbo(); // This shouldn't be needed
-
- // The context that the fbo was created in may not have depth
- // and stencil buffers, but the fbo itself might.
- fboFormat = QGLContext::currentContext()->format();
- if (attachment == QGLFramebufferObject::CombinedDepthStencil) {
- fboFormat.setDepth(true);
- fboFormat.setStencil(true);
- } else if (attachment == QGLFramebufferObject::Depth) {
- fboFormat.setDepth(true);
- fboFormat.setStencil(false);
- } else {
- fboFormat.setDepth(false);
- fboFormat.setStencil(false);
- }
-
- GLenum format = f->format().internalTextureFormat();
- reqAlpha = (format != GL_RGB
-#ifdef GL_RGB5
- && format != GL_RGB5
-#endif
-#ifdef GL_RGB8
- && format != GL_RGB8
-#endif
- );
-}
-
-QGLContext *QGLFBOGLPaintDevice::context() const
-{
- return const_cast<QGLContext *>(QGLContext::currentContext());
-}
-
-bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
-{
- QGL_FUNCP_CONTEXT;
- if (!ctx)
- return false; // Context no longer exists.
- GLenum status = ctx->contextHandle()->functions()->glCheckFramebufferStatus(GL_FRAMEBUFFER);
- switch(status) {
- case GL_NO_ERROR:
- case GL_FRAMEBUFFER_COMPLETE:
- return true;
- case GL_FRAMEBUFFER_UNSUPPORTED:
- qDebug("QGLFramebufferObject: Unsupported framebuffer format.");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
- qDebug("QGLFramebufferObject: Framebuffer incomplete attachment.");
- break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, missing attachment.");
- break;
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT
- case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");
- break;
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");
- break;
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");
- break;
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
- break;
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
- break;
-#endif
-#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
- case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
- qDebug("QGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
- break;
-#endif
- default:
- qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
- break;
- }
- return false;
-}
-
-namespace
-{
- void freeFramebufferFunc(QGLContext *ctx, GLuint id)
- {
- Q_ASSERT(ctx);
- ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &id);
- }
-
- void freeRenderbufferFunc(QGLContext *ctx, GLuint id)
- {
- Q_ASSERT(ctx);
- ctx->contextHandle()->functions()->glDeleteRenderbuffers(1, &id);
- }
-
- void freeTextureFunc(QGLContext *ctx, GLuint id)
- {
- Q_UNUSED(ctx);
- ctx->contextHandle()->functions()->glDeleteTextures(1, &id);
- }
-}
-
-void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
- QGLFramebufferObject::Attachment attachment,
- GLenum texture_target, GLenum internal_format,
- GLint samples, bool mipmap)
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
-
- funcs.initializeOpenGLFunctions();
-
- if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
- return;
-
- ctx->d_ptr->refreshCurrentFbo();
-
- size = sz;
- target = texture_target;
- // texture dimensions
-
- QT_RESET_GLERROR(); // reset error state
- GLuint fbo = 0;
- funcs.glGenFramebuffers(1, &fbo);
- funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
-
- GLuint texture = 0;
- GLuint color_buffer = 0;
- GLuint depth_buffer = 0;
- GLuint stencil_buffer = 0;
-
- QT_CHECK_GLERROR();
- // init texture
- if (samples == 0) {
- funcs.glGenTextures(1, &texture);
- funcs.glBindTexture(target, texture);
- funcs.glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- if (mipmap) {
- int width = size.width();
- int height = size.height();
- int level = 0;
- while (width > 1 || height > 1) {
- width = qMax(1, width >> 1);
- height = qMax(1, height >> 1);
- ++level;
- funcs.glTexImage2D(target, level, internal_format, width, height, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- }
- }
- funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- target, texture, 0);
-
- QT_CHECK_GLERROR();
- valid = checkFramebufferStatus();
- funcs.glBindTexture(target, 0);
-
- color_buffer = 0;
- } else {
- mipmap = false;
- GLint maxSamples;
- funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
-
- samples = qBound(0, int(samples), int(maxSamples));
-
- funcs.glGenRenderbuffers(1, &color_buffer);
- funcs.glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) && samples > 0) {
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- internal_format, size.width(), size.height());
- } else {
- samples = 0;
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, internal_format,
- size.width(), size.height());
- }
-
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER, color_buffer);
-
- QT_CHECK_GLERROR();
- valid = checkFramebufferStatus();
-
- if (valid)
- funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
- }
-
- // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
- // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
- // might not be supported while separate buffers are, according to QTBUG-12861.
-
- if (attachment == QGLFramebufferObject::CombinedDepthStencil
- && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil)) {
- // depth and stencil buffer needs another extension
- funcs.glGenRenderbuffers(1, &depth_buffer);
- funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
- Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
-#ifndef Q_OS_WASM
- if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH24_STENCIL8, size.width(), size.height());
- else
- funcs.glRenderbufferStorage(GL_RENDERBUFFER,
- GL_DEPTH24_STENCIL8, size.width(), size.height());
-
- stencil_buffer = depth_buffer;
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, depth_buffer);
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, stencil_buffer);
-#else
- // webgl does not allow separate depth and stencil attachments
- if (samples != 0) {
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_STENCIL, size.width(), size.height());
- } else {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_STENCIL,
- size.width(), size.height());
- }
- stencil_buffer = depth_buffer;
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, depth_buffer);
-#endif
-
- valid = checkFramebufferStatus();
- if (!valid) {
- funcs.glDeleteRenderbuffers(1, &depth_buffer);
- stencil_buffer = depth_buffer = 0;
- }
- }
-
- if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil
- || (attachment == QGLFramebufferObject::Depth)))
- {
- funcs.glGenRenderbuffers(1, &depth_buffer);
- funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
- Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
- if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
-#ifdef QT_OPENGL_ES
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_COMPONENT24_OES, size.width(), size.height());
- } else {
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_COMPONENT16, size.width(), size.height());
- }
-#else
- if (ctx->contextHandle()->isOpenGLES()) {
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24))
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_COMPONENT24, size.width(), size.height());
- else
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_COMPONENT16, size.width(), size.height());
- } else {
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
- GL_DEPTH_COMPONENT, size.width(), size.height());
- }
-#endif
- } else {
-#ifdef QT_OPENGL_ES
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,
- size.width(), size.height());
- } else {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
- size.width(), size.height());
- }
-#else
- if (ctx->contextHandle()->isOpenGLES()) {
- if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,
- size.width(), size.height());
- } else {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
- size.width(), size.height());
- }
- } else {
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());
- }
-#endif
- }
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, depth_buffer);
- valid = checkFramebufferStatus();
- if (!valid) {
- funcs.glDeleteRenderbuffers(1, &depth_buffer);
- depth_buffer = 0;
- }
- }
-
- if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) {
- funcs.glGenRenderbuffers(1, &stencil_buffer);
- funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer);
- Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));
-
-#ifdef QT_OPENGL_ES
- GLenum storage = GL_STENCIL_INDEX8;
-#else
- GLenum storage = ctx->contextHandle()->isOpenGLES() ? GL_STENCIL_INDEX8 : GL_STENCIL_INDEX;
-#endif
-
- if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
- funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage, size.width(), size.height());
- else
- funcs.glRenderbufferStorage(GL_RENDERBUFFER, storage, size.width(), size.height());
-
- funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, stencil_buffer);
- valid = checkFramebufferStatus();
- if (!valid) {
- funcs.glDeleteRenderbuffers(1, &stencil_buffer);
- stencil_buffer = 0;
- }
- }
-
- // The FBO might have become valid after removing the depth or stencil buffer.
- valid = checkFramebufferStatus();
-
- if (depth_buffer && stencil_buffer) {
- fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
- } else if (depth_buffer) {
- fbo_attachment = QGLFramebufferObject::Depth;
- } else {
- fbo_attachment = QGLFramebufferObject::NoAttachment;
- }
-
- funcs.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo);
- if (valid) {
- fbo_guard = createSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
- if (color_buffer)
- color_buffer_guard = createSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
- else
- texture_guard = createSharedResourceGuard(ctx, texture, freeTextureFunc);
- if (depth_buffer)
- depth_buffer_guard = createSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
- if (stencil_buffer) {
- if (stencil_buffer == depth_buffer)
- stencil_buffer_guard = depth_buffer_guard;
- else
- stencil_buffer_guard = createSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
- }
- } else {
- if (color_buffer)
- funcs.glDeleteRenderbuffers(1, &color_buffer);
- else
- funcs.glDeleteTextures(1, &texture);
- if (depth_buffer)
- funcs.glDeleteRenderbuffers(1, &depth_buffer);
- if (stencil_buffer && depth_buffer != stencil_buffer)
- funcs.glDeleteRenderbuffers(1, &stencil_buffer);
- funcs.glDeleteFramebuffers(1, &fbo);
- }
- QT_CHECK_GLERROR();
-
- format.setTextureTarget(target);
- format.setSamples(int(samples));
- format.setAttachment(fbo_attachment);
- format.setInternalTextureFormat(internal_format);
- format.setMipmap(mipmap);
-
- glDevice.setFBO(q, attachment);
-}
-
-/*!
- \class QGLFramebufferObject
- \inmodule QtOpenGL
- \brief The QGLFramebufferObject class encapsulates an OpenGL framebuffer object.
- \since 4.2
-
- \obsolete
-
- \ingroup painting-3D
-
- The QGLFramebufferObject class encapsulates an OpenGL framebuffer
- object, defined by the \c{GL_EXT_framebuffer_object} extension. In
- addition it provides a rendering surface that can be painted on
- with a QPainter, rendered to using native GL calls, or both. This
- surface can be bound and used as a regular texture in your own GL
- drawing code. By default, the QGLFramebufferObject class
- generates a 2D GL texture (using the \c{GL_TEXTURE_2D} target),
- which is used as the internal rendering target.
-
- \b{It is important to have a current GL context when creating a
- QGLFramebufferObject, otherwise initialization will fail.}
-
- OpenGL framebuffer objects and pbuffers (see
- \l{QGLPixelBuffer}{QGLPixelBuffer}) can both be used to render to
- offscreen surfaces, but there are a number of advantages with
- using framebuffer objects instead of pbuffers:
-
- \list 1
- \li A framebuffer object does not require a separate rendering
- context, so no context switching will occur when switching
- rendering targets. There is an overhead involved in switching
- targets, but in general it is cheaper than a context switch to a
- pbuffer.
-
- \li Rendering to dynamic textures (i.e. render-to-texture
- functionality) works on all platforms. No need to do explicit copy
- calls from a render buffer into a texture, as was necessary on
- systems that did not support the \c{render_texture} extension.
-
- \li It is possible to attach several rendering buffers (or texture
- objects) to the same framebuffer object, and render to all of them
- without doing a context switch.
-
- \li The OpenGL framebuffer extension is a pure GL extension with no
- system dependant WGL, CGL, or GLX parts. This makes using
- framebuffer objects more portable.
- \endlist
-
- When using a QPainter to paint to a QGLFramebufferObject you should take
- care that the QGLFramebufferObject is created with the CombinedDepthStencil
- attachment for QPainter to be able to render correctly.
- Note that you need to create a QGLFramebufferObject with more than one
- sample per pixel for primitives to be antialiased when drawing using a
- QPainter. To create a multisample framebuffer object you should use one of
- the constructors that take a QGLFramebufferObjectFormat parameter, and set
- the QGLFramebufferObjectFormat::samples() property to a non-zero value.
-
- When painting to a QGLFramebufferObject using QPainter, the state of
- the current GL context will be altered by the paint engine to reflect
- its needs. Applications should not rely upon the GL state being reset
- to its original conditions, particularly the current shader program,
- GL viewport, texture units, and drawing modes.
-
- For multisample framebuffer objects a color render buffer is created,
- otherwise a texture with the specified texture target is created.
- The color render buffer or texture will have the specified internal
- format, and will be bound to the \c GL_COLOR_ATTACHMENT0
- attachment in the framebuffer object.
-
- If you want to use a framebuffer object with multisampling enabled
- as a texture, you first need to copy from it to a regular framebuffer
- object using QGLContext::blitFramebuffer().
-
- \section1 Threading
-
- As of Qt 4.8, it's possible to draw into a QGLFramebufferObject
- using a QPainter in a separate thread. Note that OpenGL 2.0 or
- OpenGL ES 2.0 is required for this to work.
-
- \note This class has been deprecated in favor of QOpenGLFramebufferObject.
-*/
-
-
-/*!
- \enum QGLFramebufferObject::Attachment
- \since 4.3
-
- This enum type is used to configure the depth and stencil buffers
- attached to the framebuffer object when it is created.
-
- \value NoAttachment No attachment is added to the framebuffer object. Note that the
- OpenGL depth and stencil tests won't work when rendering to a
- framebuffer object without any depth or stencil buffers.
- This is the default value.
-
- \value CombinedDepthStencil If the \c GL_EXT_packed_depth_stencil extension is present,
- a combined depth and stencil buffer is attached.
- If the extension is not present, only a depth buffer is attached.
-
- \value Depth A depth buffer is attached to the framebuffer object.
-
- \sa attachment()
-*/
-
-
-/*! \fn QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
-
- Constructs an OpenGL framebuffer object and binds a 2D GL texture
- to the buffer of the size \a size. The texture is bound to the
- \c GL_COLOR_ATTACHMENT0 target in the framebuffer object.
-
- The \a target parameter is used to specify the GL texture
- target. The default target is \c GL_TEXTURE_2D. Keep in mind that
- \c GL_TEXTURE_2D textures must have a power of 2 width and height
- (e.g. 256x512), unless you are using OpenGL 2.0 or higher.
-
- By default, no depth and stencil buffers are attached. This behavior
- can be toggled using one of the overloaded constructors.
-
- The default internal texture format is \c GL_RGBA8 for desktop
- OpenGL, and \c GL_RGBA for OpenGL/ES.
-
- It is important that you have a current GL context set when
- creating the QGLFramebufferObject, otherwise the initialization
- will fail.
-
- \sa size(), texture(), attachment()
-*/
-
-QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- d->init(this, size, NoAttachment, target,
-#ifndef QT_OPENGL_ES_2
- QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8
-#else
- GL_RGBA
-#endif
- );
-}
-
-/*! \overload
-
- Constructs an OpenGL framebuffer object and binds a 2D GL texture
- to the buffer of the given \a width and \a height.
-
- \sa size(), texture()
-*/
-QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- d->init(this, QSize(width, height), NoAttachment, target,
-#ifndef QT_OPENGL_ES_2
- QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8
-#else
- GL_RGBA
-#endif
- );
-}
-
-/*! \overload
-
- Constructs an OpenGL framebuffer object of the given \a size based on the
- supplied \a format.
-*/
-
-QGLFramebufferObject::QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),
- format.samples(), format.mipmap());
-}
-
-/*! \overload
-
- Constructs an OpenGL framebuffer object of the given \a width and \a height
- based on the supplied \a format.
-*/
-
-QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),
- format.internalTextureFormat(), format.samples(), format.mipmap());
-}
-
-/*! \overload
-
- Constructs an OpenGL framebuffer object and binds a texture to the
- buffer of the given \a width and \a height.
-
- The \a attachment parameter describes the depth/stencil buffer
- configuration, \a target the texture target and \a internal_format
- the internal texture format. The default texture target is \c
- GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8
- for desktop OpenGL and \c GL_RGBA for OpenGL/ES.
-
- \sa size(), texture(), attachment()
-*/
-QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment attachment,
- GLenum target, GLenum internal_format)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- if (!internal_format)
-#ifdef QT_OPENGL_ES_2
- internal_format = GL_RGBA;
-#else
- internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
-#endif
- d->init(this, QSize(width, height), attachment, target, internal_format);
-}
-
-/*! \overload
-
- Constructs an OpenGL framebuffer object and binds a texture to the
- buffer of the given \a size.
-
- The \a attachment parameter describes the depth/stencil buffer
- configuration, \a target the texture target and \a internal_format
- the internal texture format. The default texture target is \c
- GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8
- for desktop OpenGL and \c GL_RGBA for OpenGL/ES.
-
- \sa size(), texture(), attachment()
-*/
-QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachment,
- GLenum target, GLenum internal_format)
- : d_ptr(new QGLFramebufferObjectPrivate)
-{
- Q_D(QGLFramebufferObject);
- if (!internal_format)
-#ifdef QT_OPENGL_ES_2
- internal_format = GL_RGBA;
-#else
- internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
-#endif
- d->init(this, size, attachment, target, internal_format);
-}
-
-/*!
- \fn QGLFramebufferObject::~QGLFramebufferObject()
-
- Destroys the framebuffer object and frees any allocated resources.
-*/
-QGLFramebufferObject::~QGLFramebufferObject()
-{
- Q_D(QGLFramebufferObject);
-
- delete d->engine;
-
- if (d->texture_guard)
- d->texture_guard->free();
- if (d->color_buffer_guard)
- d->color_buffer_guard->free();
- if (d->depth_buffer_guard)
- d->depth_buffer_guard->free();
- if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard)
- d->stencil_buffer_guard->free();
- if (d->fbo_guard)
- d->fbo_guard->free();
-}
-
-/*!
- \fn bool QGLFramebufferObject::isValid() const
-
- Returns \c true if the framebuffer object is valid.
-
- The framebuffer can become invalid if the initialization process
- fails, the user attaches an invalid buffer to the framebuffer
- object, or a non-power of two width/height is specified as the
- texture size if the texture target is \c{GL_TEXTURE_2D}.
- The non-power of two limitation does not apply if the OpenGL version
- is 2.0 or higher, or if the GL_ARB_texture_non_power_of_two extension
- is present.
-
- The framebuffer can also become invalid if the QGLContext that
- the framebuffer was created within is destroyed and there are
- no other shared contexts that can take over ownership of the
- framebuffer.
-*/
-bool QGLFramebufferObject::isValid() const
-{
- Q_D(const QGLFramebufferObject);
- return d->valid && d->fbo_guard && d->fbo_guard->id();
-}
-
-/*!
- \fn bool QGLFramebufferObject::bind()
-
- Switches rendering from the default, windowing system provided
- framebuffer to this framebuffer object.
- Returns \c true upon success, false otherwise.
-
- \sa release()
-*/
-bool QGLFramebufferObject::bind()
-{
- if (!isValid())
- return false;
- Q_D(QGLFramebufferObject);
- QGL_FUNC_CONTEXT;
- if (!ctx)
- return false; // Context no longer exists.
- const QGLContext *current = QGLContext::currentContext();
-#ifdef QT_DEBUG
- if (!current ||
- QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
- {
- qWarning("QGLFramebufferObject::bind() called from incompatible context");
- }
-#endif
- d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
- d->valid = d->checkFramebufferStatus();
- if (d->valid && current)
- current->d_ptr->setCurrentFbo(d->fbo());
- return d->valid;
-}
-
-/*!
- \fn bool QGLFramebufferObject::release()
-
- Switches rendering back to the default, windowing system provided
- framebuffer.
- Returns \c true upon success, false otherwise.
-
- \sa bind()
-*/
-bool QGLFramebufferObject::release()
-{
- if (!isValid())
- return false;
- Q_D(QGLFramebufferObject);
- QGL_FUNC_CONTEXT;
- if (!ctx)
- return false; // Context no longer exists.
-
- const QGLContext *current = QGLContext::currentContext();
-
-#ifdef QT_DEBUG
- if (!current ||
- QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
- {
- qWarning("QGLFramebufferObject::release() called from incompatible context");
- }
-#endif
-
- if (current) {
- current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo);
- d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo);
- }
-
- return true;
-}
-
-/*!
- \fn GLuint QGLFramebufferObject::texture() const
-
- Returns the texture id for the texture attached as the default
- rendering target in this framebuffer object. This texture id can
- be bound as a normal texture in your own GL code.
-
- If a multisample framebuffer object is used then the value returned
- from this function will be invalid.
-*/
-GLuint QGLFramebufferObject::texture() const
-{
- Q_D(const QGLFramebufferObject);
- return d->texture_guard ? d->texture_guard->id() : 0;
-}
-
-/*!
- \fn QSize QGLFramebufferObject::size() const
-
- Returns the size of the texture attached to this framebuffer
- object.
-*/
-QSize QGLFramebufferObject::size() const
-{
- Q_D(const QGLFramebufferObject);
- return d->size;
-}
-
-/*!
- Returns the format of this framebuffer object.
-*/
-QGLFramebufferObjectFormat QGLFramebufferObject::format() const
-{
- Q_D(const QGLFramebufferObject);
- return d->format;
-}
-
-/*!
- \fn QImage QGLFramebufferObject::toImage() const
-
- Returns the contents of this framebuffer object as a QImage.
-
- The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
- only when internalTextureFormat() is set to \c GL_RGB.
-
- If the rendering in the framebuffer was not done with premultiplied alpha in mind,
- create a wrapper QImage with a non-premultiplied format. This is necessary before
- performing operations like QImage::save() because otherwise the image data would get
- unpremultiplied, even though it was not premultiplied in the first place. To create
- such a wrapper without performing a copy of the pixel data, do the following:
-
- \code
- QImage fboImage(fbo.toImage());
- QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
- \endcode
-
- On QNX the back buffer is not preserved when a buffer swap occures. So this function
- might return old content.
-*/
-QImage QGLFramebufferObject::toImage() const
-{
- Q_D(const QGLFramebufferObject);
- if (!d->valid)
- return QImage();
-
- // qt_gl_read_frame_buffer doesn't work on a multisample FBO
- if (format().samples() != 0) {
- QGLFramebufferObject temp(size(), QGLFramebufferObjectFormat());
-
- QRect rect(QPoint(0, 0), size());
- blitFramebuffer(&temp, rect, const_cast<QGLFramebufferObject *>(this), rect);
-
- return temp.toImage();
- }
-
- bool wasBound = isBound();
- if (!wasBound)
- const_cast<QGLFramebufferObject *>(this)->bind();
- QImage image = qt_gl_read_frame_buffer(d->size, format().internalTextureFormat() != GL_RGB, true);
- if (!wasBound)
- const_cast<QGLFramebufferObject *>(this)->release();
-
- return image;
-}
-
-Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine)
-
-/*! \reimp */
-QPaintEngine *QGLFramebufferObject::paintEngine() const
-{
- Q_D(const QGLFramebufferObject);
- if (d->engine)
- return d->engine;
-
- QPaintEngine *engine = qt_buffer_2_engine()->engine();
- if (engine->isActive() && engine->paintDevice() != this) {
- d->engine = new QGL2PaintEngineEx;
- return d->engine;
- }
- return engine;
-}
-
-/*!
- \fn bool QGLFramebufferObject::bindDefault()
-
- Switches rendering back to the default, windowing system provided
- framebuffer.
- Returns \c true upon success, false otherwise.
-
- \sa bind(), release()
-*/
-bool QGLFramebufferObject::bindDefault()
-{
- QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());
-
- if (ctx) {
- QOpenGLFunctions functions(ctx->contextHandle());
- if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
- return false;
-
- ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo);
- functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo);
-#ifdef QT_DEBUG
- } else {
- qWarning("QGLFramebufferObject::bindDefault() called without current context.");
-#endif
- }
-
- return ctx != 0;
-}
-
-/*!
- \fn bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
-
- Returns \c true if the OpenGL \c{GL_EXT_framebuffer_object} extension
- is present on this system; otherwise returns \c false.
-*/
-bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
-{
- return qgl_hasFeature(QOpenGLFunctions::Framebuffers);
-}
-
-/*!
- \since 4.4
-
- Draws the given texture, \a textureId, to the given target rectangle,
- \a target, in OpenGL model space. The \a textureTarget should be a 2D
- texture target.
-
- The framebuffer object should be bound when calling this function.
-
- Equivalent to the corresponding QGLContext::drawTexture().
-*/
-void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
-{
- const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget);
-}
-
-/*!
- \since 4.4
-
- Draws the given texture, \a textureId, at the given \a point in OpenGL
- model space. The \a textureTarget should be a 2D texture target.
-
- The framebuffer object should be bound when calling this function.
-
- Equivalent to the corresponding QGLContext::drawTexture().
-*/
-void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
-{
- const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget);
-}
-
-/*! \reimp */
-int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
-{
- Q_D(const QGLFramebufferObject);
-
- float dpmx = qt_defaultDpiX()*100./2.54;
- float dpmy = qt_defaultDpiY()*100./2.54;
- int w = d->size.width();
- int h = d->size.height();
- switch (metric) {
- case PdmWidth:
- return w;
-
- case PdmHeight:
- return h;
-
- case PdmWidthMM:
- return qRound(w * 1000 / dpmx);
-
- case PdmHeightMM:
- return qRound(h * 1000 / dpmy);
-
- case PdmNumColors:
- return 0;
-
- case PdmDepth:
- return 32;//d->depth;
-
- case PdmDpiX:
- return qRound(dpmx * 0.0254);
-
- case PdmDpiY:
- return qRound(dpmy * 0.0254);
-
- case PdmPhysicalDpiX:
- return qRound(dpmx * 0.0254);
-
- case PdmPhysicalDpiY:
- return qRound(dpmy * 0.0254);
-
- case QPaintDevice::PdmDevicePixelRatio:
- return 1;
-
- case QPaintDevice::PdmDevicePixelRatioScaled:
- return 1 * QPaintDevice::devicePixelRatioFScale();
-
- default:
- qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
- break;
- }
- return 0;
-}
-
-/*!
- \fn GLuint QGLFramebufferObject::handle() const
-
- Returns the GL framebuffer object handle for this framebuffer
- object (returned by the \c{glGenFrameBuffersEXT()} function). This
- handle can be used to attach new images or buffers to the
- framebuffer. The user is responsible for cleaning up and
- destroying these objects.
-*/
-GLuint QGLFramebufferObject::handle() const
-{
- Q_D(const QGLFramebufferObject);
- return d->fbo();
-}
-
-/*! \fn int QGLFramebufferObject::devType() const
- \internal
-*/
-
-
-/*!
- Returns the status of the depth and stencil buffers attached to
- this framebuffer object.
-*/
-
-QGLFramebufferObject::Attachment QGLFramebufferObject::attachment() const
-{
- Q_D(const QGLFramebufferObject);
- if (d->valid)
- return d->fbo_attachment;
- return NoAttachment;
-}
-
-/*!
- \since 4.5
-
- Returns \c true if the framebuffer object is currently bound to a context,
- otherwise false is returned.
-*/
-
-bool QGLFramebufferObject::isBound() const
-{
- Q_D(const QGLFramebufferObject);
- const QGLContext *current = QGLContext::currentContext();
- if (current) {
- current->d_ptr->refreshCurrentFbo();
- return current->d_ptr->current_fbo == d->fbo();
- }
-
- return false;
-}
-
-/*!
- \fn bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
-
- \since 4.6
-
- Returns \c true if the OpenGL \c{GL_EXT_framebuffer_blit} extension
- is present on this system; otherwise returns \c false.
-
- \sa blitFramebuffer()
-*/
-bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
-{
- return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
-}
-
-/*!
- \since 4.6
-
- Blits from the \a sourceRect rectangle in the \a source framebuffer
- object to the \a targetRect rectangle in the \a target framebuffer object.
-
- If \a source or \a target is \nullptr, the default framebuffer will be used
- instead of a framebuffer object as source or target respectively.
-
- The \a buffers parameter should be a mask consisting of any combination of
- \c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and
- \c GL_STENCIL_BUFFER_BIT. Any buffer type that is not present both
- in the source and target buffers is ignored.
-
- The \a sourceRect and \a targetRect rectangles may have different sizes;
- in this case \a buffers should not contain \c GL_DEPTH_BUFFER_BIT or
- \c GL_STENCIL_BUFFER_BIT. The \a filter parameter should be set to
- \c GL_LINEAR or \c GL_NEAREST, and specifies whether linear or nearest
- interpolation should be used when scaling is performed.
-
- If \a source equals \a target a copy is performed within the same buffer.
- Results are undefined if the source and target rectangles overlap and
- have different sizes. The sizes must also be the same if any of the
- framebuffer objects are multisample framebuffers.
-
- Note that the scissor test will restrict the blit area if enabled.
-
- This function will have no effect unless hasOpenGLFramebufferBlit() returns
- true.
-
- \sa hasOpenGLFramebufferBlit()
-*/
-void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
- QGLFramebufferObject *source, const QRect &sourceRect,
- GLbitfield buffers,
- GLenum filter)
-{
- const QGLContext *ctx = QGLContext::currentContext();
- if (!ctx || !ctx->contextHandle())
- return;
-
- QOpenGLExtensions functions(ctx->contextHandle());
- if (!functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
- return;
-
- QSurface *surface = ctx->contextHandle()->surface();
-
- const int height = static_cast<QWindow *>(surface)->height();
-
- const int sh = source ? source->height() : height;
- const int th = target ? target->height() : height;
-
- const int sx0 = sourceRect.left();
- const int sx1 = sourceRect.left() + sourceRect.width();
- const int sy0 = sh - (sourceRect.top() + sourceRect.height());
- const int sy1 = sh - sourceRect.top();
-
- const int tx0 = targetRect.left();
- const int tx1 = targetRect.left() + targetRect.width();
- const int ty0 = th - (targetRect.top() + targetRect.height());
- const int ty1 = th - targetRect.top();
-
- ctx->d_ptr->refreshCurrentFbo();
-
- functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
- functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
-
- functions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
- tx0, ty0, tx1, ty1,
- buffers, filter);
-
- functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo);
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h
deleted file mode 100644
index c88063cbb5..0000000000
--- a/src/opengl/qglframebufferobject.h
+++ /dev/null
@@ -1,149 +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 QGLFRAMEBUFFEROBJECT_H
-#define QGLFRAMEBUFFEROBJECT_H
-
-#include <QtOpenGL/qgl.h>
-#include <QtGui/qpaintdevice.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLFramebufferObjectPrivate;
-class QGLFramebufferObjectFormat;
-
-class Q_OPENGL_EXPORT QGLFramebufferObject : public QPaintDevice
-{
- Q_DECLARE_PRIVATE(QGLFramebufferObject)
-public:
- enum Attachment {
- NoAttachment,
- CombinedDepthStencil,
- Depth
- };
-
- QGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D);
- QGLFramebufferObject(int width, int height, GLenum target = GL_TEXTURE_2D);
-
- QGLFramebufferObject(const QSize &size, Attachment attachment,
- GLenum target = GL_TEXTURE_2D, GLenum internal_format = 0);
- QGLFramebufferObject(int width, int height, Attachment attachment,
- GLenum target = GL_TEXTURE_2D, GLenum internal_format = 0);
-
- QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format);
- QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format);
-
- virtual ~QGLFramebufferObject();
-
- QGLFramebufferObjectFormat format() const;
-
- bool isValid() const;
- bool isBound() const;
- bool bind();
- bool release();
-
- GLuint texture() const;
- QSize size() const;
- QImage toImage() const;
- Attachment attachment() const;
-
- QPaintEngine *paintEngine() const override;
- GLuint handle() const;
-
- static bool bindDefault();
-
- static bool hasOpenGLFramebufferObjects();
-
- void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
- void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-
- static bool hasOpenGLFramebufferBlit();
- static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
- QGLFramebufferObject *source, const QRect &sourceRect,
- GLbitfield buffers = GL_COLOR_BUFFER_BIT,
- GLenum filter = GL_NEAREST);
-
-protected:
- int metric(PaintDeviceMetric metric) const override;
- int devType() const override { return QInternal::FramebufferObject; }
-
-private:
- Q_DISABLE_COPY(QGLFramebufferObject)
- QScopedPointer<QGLFramebufferObjectPrivate> d_ptr;
- friend class QGLPaintDevice;
- friend class QGLFBOGLPaintDevice;
-};
-
-class QGLFramebufferObjectFormatPrivate;
-class Q_OPENGL_EXPORT QGLFramebufferObjectFormat
-{
-public:
- QGLFramebufferObjectFormat();
- QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other);
- QGLFramebufferObjectFormat &operator=(const QGLFramebufferObjectFormat &other);
- ~QGLFramebufferObjectFormat();
-
- void setSamples(int samples);
- int samples() const;
-
- void setMipmap(bool enabled);
- bool mipmap() const;
-
- void setAttachment(QGLFramebufferObject::Attachment attachment);
- QGLFramebufferObject::Attachment attachment() const;
-
- void setTextureTarget(GLenum target);
- GLenum textureTarget() const;
-
- void setInternalTextureFormat(GLenum internalTextureFormat);
- GLenum internalTextureFormat() const;
-
- bool operator==(const QGLFramebufferObjectFormat& other) const;
- bool operator!=(const QGLFramebufferObjectFormat& other) const;
-
-private:
- QGLFramebufferObjectFormatPrivate *d;
-
- void detach();
-};
-
-QT_END_NAMESPACE
-
-#endif // QGLFRAMEBUFFEROBJECT_H
diff --git a/src/opengl/qglframebufferobject_p.h b/src/opengl/qglframebufferobject_p.h
deleted file mode 100644
index 9d536527c3..0000000000
--- a/src/opengl/qglframebufferobject_p.h
+++ /dev/null
@@ -1,157 +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 QGLFRAMEBUFFEROBJECT_P_H
-#define QGLFRAMEBUFFEROBJECT_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 <qglframebufferobject.h>
-#include <private/qglpaintdevice_p.h>
-#include <private/qgl_p.h>
-#include <private/qopenglextensions_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QGLFramebufferObjectFormatPrivate
-{
-public:
- QGLFramebufferObjectFormatPrivate()
- : ref(1),
- samples(0),
- attachment(QGLFramebufferObject::NoAttachment),
- target(GL_TEXTURE_2D),
- mipmap(false)
- {
-#ifndef QT_OPENGL_ES_2
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- const bool isES = ctx ? ctx->isOpenGLES() : QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL;
- internal_format = isES ? GL_RGBA : GL_RGBA8;
-#else
- internal_format = GL_RGBA;
-#endif
- }
- QGLFramebufferObjectFormatPrivate
- (const QGLFramebufferObjectFormatPrivate *other)
- : ref(1),
- samples(other->samples),
- attachment(other->attachment),
- target(other->target),
- internal_format(other->internal_format),
- mipmap(other->mipmap)
- {
- }
- bool equals(const QGLFramebufferObjectFormatPrivate *other)
- {
- return samples == other->samples &&
- attachment == other->attachment &&
- target == other->target &&
- internal_format == other->internal_format &&
- mipmap == other->mipmap;
- }
-
- QAtomicInt ref;
- int samples;
- QGLFramebufferObject::Attachment attachment;
- GLenum target;
- GLenum internal_format;
- uint mipmap : 1;
-};
-
-class QGLFBOGLPaintDevice : public QGLPaintDevice
-{
-public:
- virtual QPaintEngine* paintEngine() const override {return fbo->paintEngine();}
- virtual QSize size() const override {return fbo->size();}
- virtual QGLContext* context() const override;
- virtual QGLFormat format() const override {return fboFormat;}
- virtual bool alphaRequested() const override { return reqAlpha; }
-
- void setFBO(QGLFramebufferObject* f,
- QGLFramebufferObject::Attachment attachment);
-
-private:
- QGLFramebufferObject* fbo;
- QGLFormat fboFormat;
- bool reqAlpha;
-};
-
-class QGLFramebufferObjectPrivate
-{
-public:
- QGLFramebufferObjectPrivate() : fbo_guard(nullptr), texture_guard(nullptr), depth_buffer_guard(nullptr)
- , stencil_buffer_guard(nullptr), color_buffer_guard(nullptr)
- , valid(false), engine(nullptr) {}
- ~QGLFramebufferObjectPrivate() {}
-
- void init(QGLFramebufferObject *q, const QSize& sz,
- QGLFramebufferObject::Attachment attachment,
- GLenum internal_format, GLenum texture_target,
- GLint samples = 0, bool mipmap = false);
- bool checkFramebufferStatus() const;
- QGLSharedResourceGuardBase *fbo_guard;
- QGLSharedResourceGuardBase *texture_guard;
- QGLSharedResourceGuardBase *depth_buffer_guard;
- QGLSharedResourceGuardBase *stencil_buffer_guard;
- QGLSharedResourceGuardBase *color_buffer_guard;
- GLenum target;
- QSize size;
- QGLFramebufferObjectFormat format;
- uint valid : 1;
- QGLFramebufferObject::Attachment fbo_attachment;
- mutable QPaintEngine *engine;
- QGLFBOGLPaintDevice glDevice;
- QOpenGLExtensions funcs;
-
- inline GLuint fbo() const { return fbo_guard ? fbo_guard->id() : 0; }
-};
-
-
-QT_END_NAMESPACE
-
-#endif // QGLFRAMEBUFFEROBJECT_P_H
diff --git a/src/opengl/qglfunctions.cpp b/src/opengl/qglfunctions.cpp
deleted file mode 100644
index b20311bec4..0000000000
--- a/src/opengl/qglfunctions.cpp
+++ /dev/null
@@ -1,1330 +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 "qglfunctions.h"
-#include "qgl_p.h"
-#include "QtGui/private/qopenglcontext_p.h"
-#include <private/qopengl_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QGLFunctions
- \inmodule QtOpenGL
- \brief The QGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
- \since 4.8
- \obsolete
- \ingroup painting-3D
-
- OpenGL ES 2.0 defines a subset of the OpenGL specification that is
- common across many desktop and embedded OpenGL implementations.
- However, it can be difficult to use the functions from that subset
- because they need to be resolved manually on desktop systems.
-
- QGLFunctions provides a guaranteed API that is available on all
- OpenGL systems and takes care of function resolution on systems
- that need it. The recommended way to use QGLFunctions is by
- direct inheritance:
-
- \snippet code/src_opengl_qglfunctions.cpp 0
-
- The \c{paintGL()} function can then use any of the OpenGL ES 2.0
- functions without explicit resolution, such as glActiveTexture()
- in the following example:
-
- \snippet code/src_opengl_qglfunctions.cpp 1
-
- QGLFunctions can also be used directly for ad-hoc invocation
- of OpenGL ES 2.0 functions on all platforms:
-
- \snippet code/src_opengl_qglfunctions.cpp 2
-
- QGLFunctions provides wrappers for all OpenGL ES 2.0 functions,
- except those like \c{glDrawArrays()}, \c{glViewport()}, and
- \c{glBindTexture()} that don't have portability issues.
-
- Including the header for QGLFunctions will also define all of
- the OpenGL ES 2.0 macro constants that are not already defined by
- the system's OpenGL headers, such as \c{GL_TEXTURE1} above.
-
- The hasOpenGLFeature() and openGLFeatures() functions can be used
- to determine if the OpenGL implementation has a major OpenGL ES 2.0
- feature. For example, the following checks if non power of two
- textures are available:
-
- \snippet code/src_opengl_qglfunctions.cpp 3
-
- \note This class has been deprecated in favor of QOpenGLFunctions.
-*/
-
-/*!
- \enum QGLFunctions::OpenGLFeature
- This enum defines OpenGL ES 2.0 features that may be optional
- on other platforms.
-
- \value Multitexture glActiveTexture() function is available.
- \value Shaders Shader functions are available.
- \value Buffers Vertex and index buffer functions are available.
- \value Framebuffers Framebuffer object functions are available.
- \value BlendColor glBlendColor() is available.
- \value BlendEquation glBlendEquation() is available.
- \value BlendEquationSeparate glBlendEquationSeparate() is available.
- \value BlendFuncSeparate glBlendFuncSeparate() is available.
- \value BlendSubtract Blend subtract mode is available.
- \value CompressedTextures Compressed texture functions are available.
- \value Multisample glSampleCoverage() function is available.
- \value StencilSeparate Separate stencil functions are available.
- \value NPOTTextures Non power of two textures are available.
-*/
-
-// Hidden private fields for additional extension data.
-struct QGLFunctionsPrivateEx : public QGLFunctionsPrivate, public QOpenGLSharedResource
-{
- QGLFunctionsPrivateEx(QOpenGLContext *context)
- : QGLFunctionsPrivate(QGLContext::fromOpenGLContext(context))
- , QOpenGLSharedResource(context->shareGroup())
- , m_features(-1)
- {
- funcs = new QOpenGLFunctions(context);
- funcs->initializeOpenGLFunctions();
- }
-
- ~QGLFunctionsPrivateEx()
- {
- delete funcs;
- }
-
- void invalidateResource() override
- {
- m_features = -1;
- }
-
- void freeResource(QOpenGLContext *) override
- {
- // no gl resources to free
- }
-
- int m_features;
-};
-
-Q_GLOBAL_STATIC(QOpenGLMultiGroupSharedResource, qt_gl_functions_resource)
-
-static QGLFunctionsPrivateEx *qt_gl_functions(const QGLContext *context = 0)
-{
- if (!context)
- context = QGLContext::currentContext();
- Q_ASSERT(context);
- QGLFunctionsPrivateEx *funcs =
- reinterpret_cast<QGLFunctionsPrivateEx *>
- (qt_gl_functions_resource()->value<QGLFunctionsPrivateEx>(context->contextHandle()));
- return funcs;
-}
-
-/*!
- Constructs a default function resolver. The resolver cannot
- be used until initializeGLFunctions() is called to specify
- the context.
-
- \sa initializeGLFunctions()
-*/
-QGLFunctions::QGLFunctions()
- : d_ptr(0)
-{
-}
-
-/*!
- Constructs a function resolver for \a context. If \a context
- is \nullptr, then the resolver will be created for the current
- QGLContext.
-
- An object constructed in this way can only be used with \a context
- and other contexts that share with it. Use initializeGLFunctions()
- to change the object's context association.
-
- \sa initializeGLFunctions()
-*/
-QGLFunctions::QGLFunctions(const QGLContext *context)
- : d_ptr(qt_gl_functions(context))
-{
-}
-
-/*!
- \fn QGLFunctions::~QGLFunctions()
-
- Destroys this function resolver.
-*/
-
-static int qt_gl_resolve_features()
-{
- QOpenGLContext *ctx = QOpenGLContext::currentContext();
- if (ctx->isOpenGLES()) {
- // OpenGL ES 2
- int features = QGLFunctions::Multitexture |
- QGLFunctions::Shaders |
- QGLFunctions::Buffers |
- QGLFunctions::Framebuffers |
- QGLFunctions::BlendColor |
- QGLFunctions::BlendEquation |
- QGLFunctions::BlendEquationSeparate |
- QGLFunctions::BlendFuncSeparate |
- QGLFunctions::BlendSubtract |
- QGLFunctions::CompressedTextures |
- QGLFunctions::Multisample |
- QGLFunctions::StencilSeparate;
- QOpenGLExtensionMatcher extensions;
- if (extensions.match("GL_OES_texture_npot"))
- features |= QGLFunctions::NPOTTextures;
- if (extensions.match("GL_IMG_texture_npot"))
- features |= QGLFunctions::NPOTTextures;
- return features;
- } else {
- // OpenGL
- int features = 0;
- QGLFormat::OpenGLVersionFlags versions = QGLFormat::openGLVersionFlags();
- QOpenGLExtensionMatcher extensions;
-
- // Recognize features by extension name.
- if (extensions.match("GL_ARB_multitexture"))
- features |= QGLFunctions::Multitexture;
- if (extensions.match("GL_ARB_shader_objects"))
- features |= QGLFunctions::Shaders;
- if (extensions.match("GL_EXT_framebuffer_object") ||
- extensions.match("GL_ARB_framebuffer_object"))
- features |= QGLFunctions::Framebuffers;
- if (extensions.match("GL_EXT_blend_color"))
- features |= QGLFunctions::BlendColor;
- if (extensions.match("GL_EXT_blend_equation_separate"))
- features |= QGLFunctions::BlendEquationSeparate;
- if (extensions.match("GL_EXT_blend_func_separate"))
- features |= QGLFunctions::BlendFuncSeparate;
- if (extensions.match("GL_EXT_blend_subtract"))
- features |= QGLFunctions::BlendSubtract;
- if (extensions.match("GL_ARB_texture_compression"))
- features |= QGLFunctions::CompressedTextures;
- if (extensions.match("GL_ARB_multisample"))
- features |= QGLFunctions::Multisample;
- if (extensions.match("GL_ARB_texture_non_power_of_two"))
- features |= QGLFunctions::NPOTTextures;
-
- // Recognize features by minimum OpenGL version.
- if (versions & QGLFormat::OpenGL_Version_1_2) {
- features |= QGLFunctions::BlendColor |
- QGLFunctions::BlendEquation;
- }
- if (versions & QGLFormat::OpenGL_Version_1_3) {
- features |= QGLFunctions::Multitexture |
- QGLFunctions::CompressedTextures |
- QGLFunctions::Multisample;
- }
- if (versions & QGLFormat::OpenGL_Version_1_4)
- features |= QGLFunctions::BlendFuncSeparate;
- if (versions & QGLFormat::OpenGL_Version_1_5)
- features |= QGLFunctions::Buffers;
- if (versions & QGLFormat::OpenGL_Version_2_0) {
- features |= QGLFunctions::Shaders |
- QGLFunctions::StencilSeparate |
- QGLFunctions::BlendEquationSeparate |
- QGLFunctions::NPOTTextures;
- }
- return features;
- }
-}
-
-/*!
- Returns the set of features that are present on this system's
- OpenGL implementation.
-
- It is assumed that the QGLContext associated with this function
- resolver is current.
-
- \sa hasOpenGLFeature()
-*/
-QGLFunctions::OpenGLFeatures QGLFunctions::openGLFeatures() const
-{
- QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr);
- if (!d)
- return { };
- if (d->m_features == -1)
- d->m_features = qt_gl_resolve_features();
- return QGLFunctions::OpenGLFeatures(d->m_features);
-}
-
-/*!
- Returns \c true if \a feature is present on this system's OpenGL
- implementation; false otherwise.
-
- It is assumed that the QGLContext associated with this function
- resolver is current.
-
- \sa openGLFeatures()
-*/
-bool QGLFunctions::hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const
-{
- QGLFunctionsPrivateEx *d = static_cast<QGLFunctionsPrivateEx *>(d_ptr);
- if (!d)
- return false;
- if (d->m_features == -1)
- d->m_features = qt_gl_resolve_features();
- return (d->m_features & int(feature)) != 0;
-}
-
-/*!
- Initializes GL function resolution for \a context. If \a context
- is \nullptr, then the current QGLContext will be used.
-
- After calling this function, the QGLFunctions object can only be
- used with \a context and other contexts that share with it.
- Call initializeGLFunctions() again to change the object's context
- association.
-*/
-void QGLFunctions::initializeGLFunctions(const QGLContext *context)
-{
- d_ptr = qt_gl_functions(context);
-}
-
-/*!
- \fn void QGLFunctions::glActiveTexture(GLenum texture)
-
- Convenience function that calls glActiveTexture(\a texture).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glActiveTexture.xml}{glActiveTexture()}.
-*/
-
-/*!
- \fn void QGLFunctions::glAttachShader(GLuint program, GLuint shader)
-
- Convenience function that calls glAttachShader(\a program, \a shader).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glAttachShader.xml}{glAttachShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name)
-
- Convenience function that calls glBindAttribLocation(\a program, \a index, \a name).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBindAttribLocation.xml}{glBindAttribLocation()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
-
- Convenience function that calls glBindBuffer(\a target, \a buffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBindBuffer.xml}{glBindBuffer()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
-
- Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
-
- Note that Qt will translate a \a framebuffer argument of 0 to the currently
- bound QOpenGLContext's defaultFramebufferObject().
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBindFramebuffer.xml}{glBindFramebuffer()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer)
-
- Convenience function that calls glBindRenderbuffer(\a target, \a renderbuffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBindRenderbuffer.xml}{glBindRenderbuffer()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-
- Convenience function that calls glBlendColor(\a red, \a green, \a blue, \a alpha).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendColor.xml}{glBlendColor()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBlendEquation(GLenum mode)
-
- Convenience function that calls glBlendEquation(\a mode).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquation.xml}{glBlendEquation()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
-
- Convenience function that calls glBlendEquationSeparate(\a modeRGB, \a modeAlpha).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendEquationSeparate.xml}{glBlendEquationSeparate()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-
- Convenience function that calls glBlendFuncSeparate(\a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBlendFuncSeparate.xml}{glBlendFuncSeparate()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
-
- Convenience function that calls glBufferData(\a target, \a size, \a data, \a usage).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferData.xml}{glBufferData()}.
-*/
-
-/*!
- \fn void QGLFunctions::glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
-
- Convenience function that calls glBufferSubData(\a target, \a offset, \a size, \a data).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glBufferSubData.xml}{glBufferSubData()}.
-*/
-
-/*!
- \fn GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target)
-
- Convenience function that calls glCheckFramebufferStatus(\a target).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCheckFramebufferStatus.xml}{glCheckFramebufferStatus()}.
-*/
-
-/*!
- \fn void QGLFunctions::glClearDepthf(GLclampf depth)
-
- Convenience function that calls glClearDepth(\a depth) on
- desktop OpenGL systems and glClearDepthf(\a depth) on
- embedded OpenGL ES systems.
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glClearDepthf.xml}{glClearDepthf()}.
-*/
-
-/*!
- \fn void QGLFunctions::glCompileShader(GLuint shader)
-
- Convenience function that calls glCompileShader(\a shader).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCompileShader.xml}{glCompileShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
-
- Convenience function that calls glCompressedTexImage2D(\a target, \a level, \a internalformat, \a width, \a height, \a border, \a imageSize, \a data).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexImage2D.xml}{glCompressedTexImage2D()}.
-*/
-
-/*!
- \fn void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
-
- Convenience function that calls glCompressedTexSubImage2D(\a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format, \a imageSize, \a data).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCompressedTexSubImage2D.xml}{glCompressedTexSubImage2D()}.
-*/
-
-/*!
- \fn GLuint QGLFunctions::glCreateProgram()
-
- Convenience function that calls glCreateProgram().
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateProgram.xml}{glCreateProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn GLuint QGLFunctions::glCreateShader(GLenum type)
-
- Convenience function that calls glCreateShader(\a type).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glCreateShader.xml}{glCreateShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers)
-
- Convenience function that calls glDeleteBuffers(\a n, \a buffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteBuffers.xml}{glDeleteBuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
-
- Convenience function that calls glDeleteFramebuffers(\a n, \a framebuffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteFramebuffers.xml}{glDeleteFramebuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glDeleteProgram(GLuint program)
-
- Convenience function that calls glDeleteProgram(\a program).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteProgram.xml}{glDeleteProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
-
- Convenience function that calls glDeleteRenderbuffers(\a n, \a renderbuffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteRenderbuffers.xml}{glDeleteRenderbuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glDeleteShader(GLuint shader)
-
- Convenience function that calls glDeleteShader(\a shader).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDeleteShader.xml}{glDeleteShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar)
-
- Convenience function that calls glDepthRange(\a zNear, \a zFar) on
- desktop OpenGL systems and glDepthRangef(\a zNear, \a zFar) on
- embedded OpenGL ES systems.
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDepthRangef.xml}{glDepthRangef()}.
-*/
-
-/*!
- \fn void QGLFunctions::glDetachShader(GLuint program, GLuint shader)
-
- Convenience function that calls glDetachShader(\a program, \a shader).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDetachShader.xml}{glDetachShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glDisableVertexAttribArray(GLuint index)
-
- Convenience function that calls glDisableVertexAttribArray(\a index).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glDisableVertexAttribArray.xml}{glDisableVertexAttribArray()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glEnableVertexAttribArray(GLuint index)
-
- Convenience function that calls glEnableVertexAttribArray(\a index).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glEnableVertexAttribArray.xml}{glEnableVertexAttribArray()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-
- Convenience function that calls glFramebufferRenderbuffer(\a target, \a attachment, \a renderbuffertarget, \a renderbuffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferRenderbuffer.xml}{glFramebufferRenderbuffer()}.
-*/
-
-/*!
- \fn void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-
- Convenience function that calls glFramebufferTexture2D(\a target, \a attachment, \a textarget, \a texture, \a level).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glFramebufferTexture2D.xml}{glFramebufferTexture2D()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers)
-
- Convenience function that calls glGenBuffers(\a n, \a buffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGenBuffers.xml}{glGenBuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGenerateMipmap(GLenum target)
-
- Convenience function that calls glGenerateMipmap(\a target).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGenerateMipmap.xml}{glGenerateMipmap()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers)
-
- Convenience function that calls glGenFramebuffers(\a n, \a framebuffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGenFramebuffers.xml}{glGenFramebuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
-
- Convenience function that calls glGenRenderbuffers(\a n, \a renderbuffers).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGenRenderbuffers.xml}{glGenRenderbuffers()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-
- Convenience function that calls glGetActiveAttrib(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveAttrib.xml}{glGetActiveAttrib()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-
- Convenience function that calls glGetActiveUniform(\a program, \a index, \a bufsize, \a length, \a size, \a type, \a name).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetActiveUniform.xml}{glGetActiveUniform()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-
- Convenience function that calls glGetAttachedShaders(\a program, \a maxcount, \a count, \a shaders).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttachedShaders.xml}{glGetAttachedShaders()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn int QGLFunctions::glGetAttribLocation(GLuint program, const char* name)
-
- Convenience function that calls glGetAttribLocation(\a program, \a name).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetAttribLocation.xml}{glGetAttribLocation()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
-
- Convenience function that calls glGetBufferParameteriv(\a target, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetBufferParameteriv.xml}{glGetBufferParameteriv()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
-
- Convenience function that calls glGetFramebufferAttachmentParameteriv(\a target, \a attachment, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetFramebufferAttachmentParameteriv.xml}{glGetFramebufferAttachmentParameteriv()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params)
-
- Convenience function that calls glGetProgramiv(\a program, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramiv.xml}{glGetProgramiv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
-
- Convenience function that calls glGetProgramInfoLog(\a program, \a bufsize, \a length, \a infolog).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetProgramInfoLog.xml}{glGetProgramInfoLog()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
-
- Convenience function that calls glGetRenderbufferParameteriv(\a target, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetRenderbufferParameteriv.xml}{glGetRenderbufferParameteriv()}.
-*/
-
-/*!
- \fn void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
-
- Convenience function that calls glGetShaderiv(\a shader, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderiv.xml}{glGetShaderiv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
-
- Convenience function that calls glGetShaderInfoLog(\a shader, \a bufsize, \a length, \a infolog).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderInfoLog.xml}{glGetShaderInfoLog()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-
- Convenience function that calls glGetShaderPrecisionFormat(\a shadertype, \a precisiontype, \a range, \a precision).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderPrecisionFormat.xml}{glGetShaderPrecisionFormat()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
-
- Convenience function that calls glGetShaderSource(\a shader, \a bufsize, \a length, \a source).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetShaderSource.xml}{glGetShaderSource()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params)
-
- Convenience function that calls glGetUniformfv(\a program, \a location, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformfv.xml}{glGetUniformfv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params)
-
- Convenience function that calls glGetUniformiv(\a program, \a location, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformiv.xml}{glGetUniformiv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn int QGLFunctions::glGetUniformLocation(GLuint program, const char* name)
-
- Convenience function that calls glGetUniformLocation(\a program, \a name).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetUniformLocation.xml}{glGetUniformLocation()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
-
- Convenience function that calls glGetVertexAttribfv(\a index, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribfv.xml}{glGetVertexAttribfv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
-
- Convenience function that calls glGetVertexAttribiv(\a index, \a pname, \a params).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribiv.xml}{glGetVertexAttribiv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
-
- Convenience function that calls glGetVertexAttribPointerv(\a index, \a pname, \a pointer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glGetVertexAttribPointerv.xml}{glGetVertexAttribPointerv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn GLboolean QGLFunctions::glIsBuffer(GLuint buffer)
-
- Convenience function that calls glIsBuffer(\a buffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glIsBuffer.xml}{glIsBuffer()}.
-*/
-
-/*!
- \fn GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer)
-
- Convenience function that calls glIsFramebuffer(\a framebuffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glIsFramebuffer.xml}{glIsFramebuffer()}.
-*/
-
-/*!
- \fn GLboolean QGLFunctions::glIsProgram(GLuint program)
-
- Convenience function that calls glIsProgram(\a program).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glIsProgram.xml}{glIsProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer)
-
- Convenience function that calls glIsRenderbuffer(\a renderbuffer).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glIsRenderbuffer.xml}{glIsRenderbuffer()}.
-*/
-
-/*!
- \fn GLboolean QGLFunctions::glIsShader(GLuint shader)
-
- Convenience function that calls glIsShader(\a shader).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glIsShader.xml}{glIsShader()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glLinkProgram(GLuint program)
-
- Convenience function that calls glLinkProgram(\a program).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glLinkProgram.xml}{glLinkProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glReleaseShaderCompiler()
-
- Convenience function that calls glReleaseShaderCompiler().
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glReleaseShaderCompiler.xml}{glReleaseShaderCompiler()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-
- Convenience function that calls glRenderbufferStorage(\a target, \a internalformat, \a width, \a height).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glRenderbufferStorage.xml}{glRenderbufferStorage()}.
-*/
-
-/*!
- \fn void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert)
-
- Convenience function that calls glSampleCoverage(\a value, \a invert).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glSampleCoverage.xml}{glSampleCoverage()}.
-*/
-
-/*!
- \fn void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
-
- Convenience function that calls glShaderBinary(\a n, \a shaders, \a binaryformat, \a binary, \a length).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderBinary.xml}{glShaderBinary()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
-
- Convenience function that calls glShaderSource(\a shader, \a count, \a string, \a length).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glShaderSource.xml}{glShaderSource()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
-
- Convenience function that calls glStencilFuncSeparate(\a face, \a func, \a ref, \a mask).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilFuncSeparate.xml}{glStencilFuncSeparate()}.
-*/
-
-/*!
- \fn void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask)
-
- Convenience function that calls glStencilMaskSeparate(\a face, \a mask).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilMaskSeparate.xml}{glStencilMaskSeparate()}.
-*/
-
-/*!
- \fn void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
-
- Convenience function that calls glStencilOpSeparate(\a face, \a fail, \a zfail, \a zpass).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glStencilOpSeparate.xml}{glStencilOpSeparate()}.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform1f(GLint location, GLfloat x)
-
- Convenience function that calls glUniform1f(\a location, \a x).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1f.xml}{glUniform1f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
-
- Convenience function that calls glUniform1fv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1fv.xml}{glUniform1fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform1i(GLint location, GLint x)
-
- Convenience function that calls glUniform1i(\a location, \a x).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1i.xml}{glUniform1i()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v)
-
- Convenience function that calls glUniform1iv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform1iv.xml}{glUniform1iv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y)
-
- Convenience function that calls glUniform2f(\a location, \a x, \a y).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2f.xml}{glUniform2f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
-
- Convenience function that calls glUniform2fv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2fv.xml}{glUniform2fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y)
-
- Convenience function that calls glUniform2i(\a location, \a x, \a y).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2i.xml}{glUniform2i()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v)
-
- Convenience function that calls glUniform2iv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform2iv.xml}{glUniform2iv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
-
- Convenience function that calls glUniform3f(\a location, \a x, \a y, \a z).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3f.xml}{glUniform3f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
-
- Convenience function that calls glUniform3fv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3fv.xml}{glUniform3fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z)
-
- Convenience function that calls glUniform3i(\a location, \a x, \a y, \a z).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3i.xml}{glUniform3i()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v)
-
- Convenience function that calls glUniform3iv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform3iv.xml}{glUniform3iv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-
- Convenience function that calls glUniform4f(\a location, \a x, \a y, \a z, \a w).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4f.xml}{glUniform4f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
-
- Convenience function that calls glUniform4fv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4fv.xml}{glUniform4fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
-
- Convenience function that calls glUniform4i(\a location, \a x, \a y, \a z, \a w).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4i.xml}{glUniform4i()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v)
-
- Convenience function that calls glUniform4iv(\a location, \a count, \a v).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniform4iv.xml}{glUniform4iv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-
- Convenience function that calls glUniformMatrix2fv(\a location, \a count, \a transpose, \a value).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix2fv.xml}{glUniformMatrix2fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-
- Convenience function that calls glUniformMatrix3fv(\a location, \a count, \a transpose, \a value).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix3fv.xml}{glUniformMatrix3fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-
- Convenience function that calls glUniformMatrix4fv(\a location, \a count, \a transpose, \a value).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUniformMatrix4fv.xml}{glUniformMatrix4fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glUseProgram(GLuint program)
-
- Convenience function that calls glUseProgram(\a program).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glUseProgram.xml}{glUseProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glValidateProgram(GLuint program)
-
- Convenience function that calls glValidateProgram(\a program).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glValidateProgram.xml}{glValidateProgram()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x)
-
- Convenience function that calls glVertexAttrib1f(\a indx, \a x).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1f.xml}{glVertexAttrib1f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values)
-
- Convenience function that calls glVertexAttrib1fv(\a indx, \a values).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib1fv.xml}{glVertexAttrib1fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
-
- Convenience function that calls glVertexAttrib2f(\a indx, \a x, \a y).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2f.xml}{glVertexAttrib2f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values)
-
- Convenience function that calls glVertexAttrib2fv(\a indx, \a values).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib2fv.xml}{glVertexAttrib2fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-
- Convenience function that calls glVertexAttrib3f(\a indx, \a x, \a y, \a z).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3f.xml}{glVertexAttrib3f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values)
-
- Convenience function that calls glVertexAttrib3fv(\a indx, \a values).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib3fv.xml}{glVertexAttrib3fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-
- Convenience function that calls glVertexAttrib4f(\a indx, \a x, \a y, \a z, \a w).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4f.xml}{glVertexAttrib4f()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values)
-
- Convenience function that calls glVertexAttrib4fv(\a indx, \a values).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttrib4fv.xml}{glVertexAttrib4fv()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-/*!
- \fn void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
-
- Convenience function that calls glVertexAttribPointer(\a indx, \a size, \a type, \a normalized, \a stride, \a ptr).
-
- For more information, see the OpenGL ES 2.0 documentation for
- \l{http://www.khronos.org/opengles/sdk/docs/man/glVertexAttribPointer.xml}{glVertexAttribPointer()}.
-
- This convenience function will do nothing on OpenGL ES 1.x systems.
-*/
-
-QGLFunctionsPrivate::QGLFunctionsPrivate(const QGLContext *)
- : funcs(0)
-{
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglfunctions.h b/src/opengl/qglfunctions.h
deleted file mode 100644
index d8c5249a1a..0000000000
--- a/src/opengl/qglfunctions.h
+++ /dev/null
@@ -1,1688 +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 QGLFUNCTIONS_H
-#define QGLFUNCTIONS_H
-
-#include <QtOpenGL/qgl.h>
-#include <QtGui/qopenglcontext.h>
-#include <QtGui/qopenglfunctions.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QGLFunctionsPrivate;
-
-class Q_OPENGL_EXPORT QGLFunctions
-{
-public:
- QGLFunctions();
- explicit QGLFunctions(const QGLContext *context);
- ~QGLFunctions() {}
-
- enum OpenGLFeature
- {
- Multitexture = 0x0001,
- Shaders = 0x0002,
- Buffers = 0x0004,
- Framebuffers = 0x0008,
- BlendColor = 0x0010,
- BlendEquation = 0x0020,
- BlendEquationSeparate = 0x0040,
- BlendFuncSeparate = 0x0080,
- BlendSubtract = 0x0100,
- CompressedTextures = 0x0200,
- Multisample = 0x0400,
- StencilSeparate = 0x0800,
- NPOTTextures = 0x1000
- };
- Q_DECLARE_FLAGS(OpenGLFeatures, OpenGLFeature)
-
- QGLFunctions::OpenGLFeatures openGLFeatures() const;
- bool hasOpenGLFeature(QGLFunctions::OpenGLFeature feature) const;
-
- void initializeGLFunctions(const QGLContext *context = nullptr);
-
- void glActiveTexture(GLenum texture);
- void glAttachShader(GLuint program, GLuint shader);
- void glBindAttribLocation(GLuint program, GLuint index, const char* name);
- void glBindBuffer(GLenum target, GLuint buffer);
- void glBindFramebuffer(GLenum target, GLuint framebuffer);
- void glBindRenderbuffer(GLenum target, GLuint renderbuffer);
- void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
- void glBlendEquation(GLenum mode);
- void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
- void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
- void glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage);
- void glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data);
- GLenum glCheckFramebufferStatus(GLenum target);
- void glClearDepthf(GLclampf depth);
- void glCompileShader(GLuint shader);
- void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
- void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
- GLuint glCreateProgram();
- GLuint glCreateShader(GLenum type);
- void glDeleteBuffers(GLsizei n, const GLuint* buffers);
- void glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
- void glDeleteProgram(GLuint program);
- void glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
- void glDeleteShader(GLuint shader);
- void glDepthRangef(GLclampf zNear, GLclampf zFar);
- void glDetachShader(GLuint program, GLuint shader);
- void glDisableVertexAttribArray(GLuint index);
- void glEnableVertexAttribArray(GLuint index);
- void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
- void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
- void glGenBuffers(GLsizei n, GLuint* buffers);
- void glGenerateMipmap(GLenum target);
- void glGenFramebuffers(GLsizei n, GLuint* framebuffers);
- void glGenRenderbuffers(GLsizei n, GLuint* renderbuffers);
- void glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
- void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
- void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
- int glGetAttribLocation(GLuint program, const char* name);
- void glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
- void glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
- void glGetProgramiv(GLuint program, GLenum pname, GLint* params);
- void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
- void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
- void glGetShaderiv(GLuint shader, GLenum pname, GLint* params);
- void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
- void glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
- void glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
- void glGetUniformfv(GLuint program, GLint location, GLfloat* params);
- void glGetUniformiv(GLuint program, GLint location, GLint* params);
- int glGetUniformLocation(GLuint program, const char* name);
- void glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
- void glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
- void glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer);
- GLboolean glIsBuffer(GLuint buffer);
- GLboolean glIsFramebuffer(GLuint framebuffer);
- GLboolean glIsProgram(GLuint program);
- GLboolean glIsRenderbuffer(GLuint renderbuffer);
- GLboolean glIsShader(GLuint shader);
- void glLinkProgram(GLuint program);
- void glReleaseShaderCompiler();
- void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
- void glSampleCoverage(GLclampf value, GLboolean invert);
- void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
- void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length);
- void glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
- void glStencilMaskSeparate(GLenum face, GLuint mask);
- void glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
- void glUniform1f(GLint location, GLfloat x);
- void glUniform1fv(GLint location, GLsizei count, const GLfloat* v);
- void glUniform1i(GLint location, GLint x);
- void glUniform1iv(GLint location, GLsizei count, const GLint* v);
- void glUniform2f(GLint location, GLfloat x, GLfloat y);
- void glUniform2fv(GLint location, GLsizei count, const GLfloat* v);
- void glUniform2i(GLint location, GLint x, GLint y);
- void glUniform2iv(GLint location, GLsizei count, const GLint* v);
- void glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
- void glUniform3fv(GLint location, GLsizei count, const GLfloat* v);
- void glUniform3i(GLint location, GLint x, GLint y, GLint z);
- void glUniform3iv(GLint location, GLsizei count, const GLint* v);
- void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void glUniform4fv(GLint location, GLsizei count, const GLfloat* v);
- void glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
- void glUniform4iv(GLint location, GLsizei count, const GLint* v);
- void glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
- void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
- void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
- void glUseProgram(GLuint program);
- void glValidateProgram(GLuint program);
- void glVertexAttrib1f(GLuint indx, GLfloat x);
- void glVertexAttrib1fv(GLuint indx, const GLfloat* values);
- void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
- void glVertexAttrib2fv(GLuint indx, const GLfloat* values);
- void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
- void glVertexAttrib3fv(GLuint indx, const GLfloat* values);
- void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void glVertexAttrib4fv(GLuint indx, const GLfloat* values);
- void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
-
-private:
- QGLFunctionsPrivate *d_ptr;
- static bool isInitialized(const QGLFunctionsPrivate *d) { return d != nullptr; }
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFunctions::OpenGLFeatures)
-
-struct QGLFunctionsPrivate
-{
- QGLFunctionsPrivate(const QGLContext *context = nullptr);
- QOpenGLFunctions *funcs;
-};
-
-inline void QGLFunctions::glActiveTexture(GLenum texture)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glActiveTexture(texture);
-}
-
-inline void QGLFunctions::glAttachShader(GLuint program, GLuint shader)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glAttachShader(program, shader);
-}
-
-inline void QGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBindAttribLocation(program, index, name);
-}
-
-inline void QGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBindBuffer(target, buffer);
-}
-
-inline void QGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
-{
- if (framebuffer == 0)
- framebuffer = QOpenGLContext::currentContext()->defaultFramebufferObject();
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBindFramebuffer(target, framebuffer);
-}
-
-inline void QGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBindRenderbuffer(target, renderbuffer);
-}
-
-inline void QGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBlendColor(red, green, blue, alpha);
-}
-
-inline void QGLFunctions::glBlendEquation(GLenum mode)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBlendEquation(mode);
-}
-
-inline void QGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBlendEquationSeparate(modeRGB, modeAlpha);
-}
-
-inline void QGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
-}
-
-inline void QGLFunctions::glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBufferData(target, size, data, usage);
-}
-
-inline void QGLFunctions::glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glBufferSubData(target, offset, size, data);
-}
-
-inline GLenum QGLFunctions::glCheckFramebufferStatus(GLenum target)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glCheckFramebufferStatus(target);
-}
-
-inline void QGLFunctions::glClearDepthf(GLclampf depth)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glClearDepthf(depth);
-}
-
-inline void QGLFunctions::glCompileShader(GLuint shader)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glCompileShader(shader);
-}
-
-inline void QGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
-}
-
-inline void QGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
-}
-
-inline GLuint QGLFunctions::glCreateProgram()
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glCreateProgram();
-}
-
-inline GLuint QGLFunctions::glCreateShader(GLenum type)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glCreateShader(type);
-}
-
-inline void QGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDeleteBuffers(n, buffers);
-}
-
-inline void QGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDeleteFramebuffers(n, framebuffers);
-}
-
-inline void QGLFunctions::glDeleteProgram(GLuint program)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDeleteProgram(program);
-}
-
-inline void QGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDeleteRenderbuffers(n, renderbuffers);
-}
-
-inline void QGLFunctions::glDeleteShader(GLuint shader)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDeleteShader(shader);
-}
-
-inline void QGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glDepthRangef(zNear, zFar);
-}
-
-inline void QGLFunctions::glDetachShader(GLuint program, GLuint shader)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDetachShader(program, shader);
-}
-
-inline void QGLFunctions::glDisableVertexAttribArray(GLuint index)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glDisableVertexAttribArray(index);
-}
-
-inline void QGLFunctions::glEnableVertexAttribArray(GLuint index)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glEnableVertexAttribArray(index);
-}
-
-inline void QGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
-}
-
-inline void QGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glFramebufferTexture2D(target, attachment, textarget, texture, level);
-}
-
-inline void QGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGenBuffers(n, buffers);
-}
-
-inline void QGLFunctions::glGenerateMipmap(GLenum target)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGenerateMipmap(target);
-}
-
-inline void QGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGenFramebuffers(n, framebuffers);
-}
-
-inline void QGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGenRenderbuffers(n, renderbuffers);
-}
-
-inline void QGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetActiveAttrib(program, index, bufsize, length, size, type, name);
-}
-
-inline void QGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetActiveUniform(program, index, bufsize, length, size, type, name);
-}
-
-inline void QGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetAttachedShaders(program, maxcount, count, shaders);
-}
-
-inline int QGLFunctions::glGetAttribLocation(GLuint program, const char* name)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glGetAttribLocation(program, name);
-}
-
-inline void QGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetBufferParameteriv(target, pname, params);
-}
-
-inline void QGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
-}
-
-inline void QGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetProgramiv(program, pname, params);
-}
-
-inline void QGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetProgramInfoLog(program, bufsize, length, infolog);
-}
-
-inline void QGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetRenderbufferParameteriv(target, pname, params);
-}
-
-inline void QGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetShaderiv(shader, pname, params);
-}
-
-inline void QGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetShaderInfoLog(shader, bufsize, length, infolog);
-}
-
-inline void QGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
-}
-
-inline void QGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetShaderSource(shader, bufsize, length, source);
-}
-
-inline void QGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetUniformfv(program, location, params);
-}
-
-inline void QGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetUniformiv(program, location, params);
-}
-
-inline int QGLFunctions::glGetUniformLocation(GLuint program, const char* name)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glGetUniformLocation(program, name);
-}
-
-inline void QGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetVertexAttribfv(index, pname, params);
-}
-
-inline void QGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetVertexAttribiv(index, pname, params);
-}
-
-inline void QGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glGetVertexAttribPointerv(index, pname, pointer);
-}
-
-inline GLboolean QGLFunctions::glIsBuffer(GLuint buffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glIsBuffer(buffer);
-}
-
-inline GLboolean QGLFunctions::glIsFramebuffer(GLuint framebuffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glIsFramebuffer(framebuffer);
-}
-
-inline GLboolean QGLFunctions::glIsProgram(GLuint program)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glIsProgram(program);
-}
-
-inline GLboolean QGLFunctions::glIsRenderbuffer(GLuint renderbuffer)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glIsRenderbuffer(renderbuffer);
-}
-
-inline GLboolean QGLFunctions::glIsShader(GLuint shader)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- return d_ptr->funcs->glIsShader(shader);
-}
-
-inline void QGLFunctions::glLinkProgram(GLuint program)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glLinkProgram(program);
-}
-
-inline void QGLFunctions::glReleaseShaderCompiler()
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glReleaseShaderCompiler();
-}
-
-inline void QGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glRenderbufferStorage(target, internalformat, width, height);
-}
-
-inline void QGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glSampleCoverage(value, invert);
-}
-
-inline void QGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glShaderBinary(n, shaders, binaryformat, binary, length);
-}
-
-inline void QGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glShaderSource(shader, count, string, length);
-}
-
-inline void QGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glStencilFuncSeparate(face, func, ref, mask);
-}
-
-inline void QGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glStencilMaskSeparate(face, mask);
-}
-
-inline void QGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glStencilOpSeparate(face, fail, zfail, zpass);
-}
-
-inline void QGLFunctions::glUniform1f(GLint location, GLfloat x)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform1f(location, x);
-}
-
-inline void QGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform1fv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform1i(GLint location, GLint x)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform1i(location, x);
-}
-
-inline void QGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform1iv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform2f(location, x, y);
-}
-
-inline void QGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform2fv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform2i(GLint location, GLint x, GLint y)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform2i(location, x, y);
-}
-
-inline void QGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform2iv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform3f(location, x, y, z);
-}
-
-inline void QGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform3fv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform3i(location, x, y, z);
-}
-
-inline void QGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform3iv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform4f(location, x, y, z, w);
-}
-
-inline void QGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform4fv(location, count, v);
-}
-
-inline void QGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform4i(location, x, y, z, w);
-}
-
-inline void QGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniform4iv(location, count, v);
-}
-
-inline void QGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniformMatrix2fv(location, count, transpose, value);
-}
-
-inline void QGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniformMatrix3fv(location, count, transpose, value);
-}
-
-inline void QGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUniformMatrix4fv(location, count, transpose, value);
-}
-
-inline void QGLFunctions::glUseProgram(GLuint program)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glUseProgram(program);
-}
-
-inline void QGLFunctions::glValidateProgram(GLuint program)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glValidateProgram(program);
-}
-
-inline void QGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib1f(indx, x);
-}
-
-inline void QGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib1fv(indx, values);
-}
-
-inline void QGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib2f(indx, x, y);
-}
-
-inline void QGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib2fv(indx, values);
-}
-
-inline void QGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib3f(indx, x, y, z);
-}
-
-inline void QGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib3fv(indx, values);
-}
-
-inline void QGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib4f(indx, x, y, z, w);
-}
-
-inline void QGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttrib4fv(indx, values);
-}
-
-inline void QGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
-{
- Q_ASSERT(QGLFunctions::isInitialized(d_ptr));
- d_ptr->funcs->glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
-}
-
-#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
-#endif
-#ifndef GL_ACTIVE_ATTRIBUTES
-#define GL_ACTIVE_ATTRIBUTES 0x8B89
-#endif
-#ifndef GL_ACTIVE_TEXTURE
-#define GL_ACTIVE_TEXTURE 0x84E0
-#endif
-#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
-#endif
-#ifndef GL_ACTIVE_UNIFORMS
-#define GL_ACTIVE_UNIFORMS 0x8B86
-#endif
-#ifndef GL_ALIASED_LINE_WIDTH_RANGE
-#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E
-#endif
-#ifndef GL_ALIASED_POINT_SIZE_RANGE
-#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
-#endif
-#ifndef GL_ALPHA
-#define GL_ALPHA 0x1906
-#endif
-#ifndef GL_ALPHA_BITS
-#define GL_ALPHA_BITS 0x0D55
-#endif
-#ifndef GL_ALWAYS
-#define GL_ALWAYS 0x0207
-#endif
-#ifndef GL_ARRAY_BUFFER
-#define GL_ARRAY_BUFFER 0x8892
-#endif
-#ifndef GL_ARRAY_BUFFER_BINDING
-#define GL_ARRAY_BUFFER_BINDING 0x8894
-#endif
-#ifndef GL_ATTACHED_SHADERS
-#define GL_ATTACHED_SHADERS 0x8B85
-#endif
-#ifndef GL_BACK
-#define GL_BACK 0x0405
-#endif
-#ifndef GL_BLEND
-#define GL_BLEND 0x0BE2
-#endif
-#ifndef GL_BLEND_COLOR
-#define GL_BLEND_COLOR 0x8005
-#endif
-#ifndef GL_BLEND_DST_ALPHA
-#define GL_BLEND_DST_ALPHA 0x80CA
-#endif
-#ifndef GL_BLEND_DST_RGB
-#define GL_BLEND_DST_RGB 0x80C8
-#endif
-#ifndef GL_BLEND_EQUATION
-#define GL_BLEND_EQUATION 0x8009
-#endif
-#ifndef GL_BLEND_EQUATION_ALPHA
-#define GL_BLEND_EQUATION_ALPHA 0x883D
-#endif
-#ifndef GL_BLEND_EQUATION_RGB
-#define GL_BLEND_EQUATION_RGB 0x8009
-#endif
-#ifndef GL_BLEND_SRC_ALPHA
-#define GL_BLEND_SRC_ALPHA 0x80CB
-#endif
-#ifndef GL_BLEND_SRC_RGB
-#define GL_BLEND_SRC_RGB 0x80C9
-#endif
-#ifndef GL_BLUE_BITS
-#define GL_BLUE_BITS 0x0D54
-#endif
-#ifndef GL_BOOL
-#define GL_BOOL 0x8B56
-#endif
-#ifndef GL_BOOL_VEC2
-#define GL_BOOL_VEC2 0x8B57
-#endif
-#ifndef GL_BOOL_VEC3
-#define GL_BOOL_VEC3 0x8B58
-#endif
-#ifndef GL_BOOL_VEC4
-#define GL_BOOL_VEC4 0x8B59
-#endif
-#ifndef GL_BUFFER_SIZE
-#define GL_BUFFER_SIZE 0x8764
-#endif
-#ifndef GL_BUFFER_USAGE
-#define GL_BUFFER_USAGE 0x8765
-#endif
-#ifndef GL_BYTE
-#define GL_BYTE 0x1400
-#endif
-#ifndef GL_CCW
-#define GL_CCW 0x0901
-#endif
-#ifndef GL_CLAMP_TO_EDGE
-#define GL_CLAMP_TO_EDGE 0x812F
-#endif
-#ifndef GL_COLOR_ATTACHMENT0
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#endif
-#ifndef GL_COLOR_BUFFER_BIT
-#define GL_COLOR_BUFFER_BIT 0x00004000
-#endif
-#ifndef GL_COLOR_CLEAR_VALUE
-#define GL_COLOR_CLEAR_VALUE 0x0C22
-#endif
-#ifndef GL_COLOR_WRITEMASK
-#define GL_COLOR_WRITEMASK 0x0C23
-#endif
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-#ifndef GL_COMPRESSED_TEXTURE_FORMATS
-#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
-#endif
-#ifndef GL_CONSTANT_ALPHA
-#define GL_CONSTANT_ALPHA 0x8003
-#endif
-#ifndef GL_CONSTANT_COLOR
-#define GL_CONSTANT_COLOR 0x8001
-#endif
-#ifndef GL_CULL_FACE
-#define GL_CULL_FACE 0x0B44
-#endif
-#ifndef GL_CULL_FACE_MODE
-#define GL_CULL_FACE_MODE 0x0B45
-#endif
-#ifndef GL_CURRENT_PROGRAM
-#define GL_CURRENT_PROGRAM 0x8B8D
-#endif
-#ifndef GL_CURRENT_VERTEX_ATTRIB
-#define GL_CURRENT_VERTEX_ATTRIB 0x8626
-#endif
-#ifndef GL_CW
-#define GL_CW 0x0900
-#endif
-#ifndef GL_DECR
-#define GL_DECR 0x1E03
-#endif
-#ifndef GL_DECR_WRAP
-#define GL_DECR_WRAP 0x8508
-#endif
-#ifndef GL_DELETE_STATUS
-#define GL_DELETE_STATUS 0x8B80
-#endif
-#ifndef GL_DEPTH_ATTACHMENT
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#endif
-#ifndef GL_DEPTH_BITS
-#define GL_DEPTH_BITS 0x0D56
-#endif
-#ifndef GL_DEPTH_BUFFER_BIT
-#define GL_DEPTH_BUFFER_BIT 0x00000100
-#endif
-#ifndef GL_DEPTH_CLEAR_VALUE
-#define GL_DEPTH_CLEAR_VALUE 0x0B73
-#endif
-#ifndef GL_DEPTH_COMPONENT
-#define GL_DEPTH_COMPONENT 0x1902
-#endif
-#ifndef GL_DEPTH_COMPONENT16
-#define GL_DEPTH_COMPONENT16 0x81A5
-#endif
-#ifndef GL_DEPTH_FUNC
-#define GL_DEPTH_FUNC 0x0B74
-#endif
-#ifndef GL_DEPTH_RANGE
-#define GL_DEPTH_RANGE 0x0B70
-#endif
-#ifndef GL_DEPTH_TEST
-#define GL_DEPTH_TEST 0x0B71
-#endif
-#ifndef GL_DEPTH_WRITEMASK
-#define GL_DEPTH_WRITEMASK 0x0B72
-#endif
-#ifndef GL_DITHER
-#define GL_DITHER 0x0BD0
-#endif
-#ifndef GL_DONT_CARE
-#define GL_DONT_CARE 0x1100
-#endif
-#ifndef GL_DST_ALPHA
-#define GL_DST_ALPHA 0x0304
-#endif
-#ifndef GL_DST_COLOR
-#define GL_DST_COLOR 0x0306
-#endif
-#ifndef GL_DYNAMIC_DRAW
-#define GL_DYNAMIC_DRAW 0x88E8
-#endif
-#ifndef GL_ELEMENT_ARRAY_BUFFER
-#define GL_ELEMENT_ARRAY_BUFFER 0x8893
-#endif
-#ifndef GL_ELEMENT_ARRAY_BUFFER_BINDING
-#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
-#endif
-#ifndef GL_EQUAL
-#define GL_EQUAL 0x0202
-#endif
-#ifndef GL_EXTENSIONS
-#define GL_EXTENSIONS 0x1F03
-#endif
-#ifndef GL_FALSE
-#define GL_FALSE 0
-#endif
-#ifndef GL_FASTEST
-#define GL_FASTEST 0x1101
-#endif
-#ifndef GL_FIXED
-#define GL_FIXED 0x140C
-#endif
-#ifndef GL_FLOAT
-#define GL_FLOAT 0x1406
-#endif
-#ifndef GL_FLOAT_MAT2
-#define GL_FLOAT_MAT2 0x8B5A
-#endif
-#ifndef GL_FLOAT_MAT3
-#define GL_FLOAT_MAT3 0x8B5B
-#endif
-#ifndef GL_FLOAT_MAT4
-#define GL_FLOAT_MAT4 0x8B5C
-#endif
-#ifndef GL_FLOAT_VEC2
-#define GL_FLOAT_VEC2 0x8B50
-#endif
-#ifndef GL_FLOAT_VEC3
-#define GL_FLOAT_VEC3 0x8B51
-#endif
-#ifndef GL_FLOAT_VEC4
-#define GL_FLOAT_VEC4 0x8B52
-#endif
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-#ifndef GL_FRAMEBUFFER
-#define GL_FRAMEBUFFER 0x8D40
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
-#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
-#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
-#endif
-#ifndef GL_FRAMEBUFFER_BINDING
-#define GL_FRAMEBUFFER_BINDING 0x8CA6
-#endif
-#ifndef GL_FRAMEBUFFER_COMPLETE
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
-#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
-#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
-#endif
-#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
-#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
-#endif
-#ifndef GL_FRAMEBUFFER_UNSUPPORTED
-#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
-#endif
-#ifndef GL_FRONT
-#define GL_FRONT 0x0404
-#endif
-#ifndef GL_FRONT_AND_BACK
-#define GL_FRONT_AND_BACK 0x0408
-#endif
-#ifndef GL_FRONT_FACE
-#define GL_FRONT_FACE 0x0B46
-#endif
-#ifndef GL_FUNC_ADD
-#define GL_FUNC_ADD 0x8006
-#endif
-#ifndef GL_FUNC_REVERSE_SUBTRACT
-#define GL_FUNC_REVERSE_SUBTRACT 0x800B
-#endif
-#ifndef GL_FUNC_SUBTRACT
-#define GL_FUNC_SUBTRACT 0x800A
-#endif
-#ifndef GL_GENERATE_MIPMAP_HINT
-#define GL_GENERATE_MIPMAP_HINT 0x8192
-#endif
-#ifndef GL_GEQUAL
-#define GL_GEQUAL 0x0206
-#endif
-#ifndef GL_GREATER
-#define GL_GREATER 0x0204
-#endif
-#ifndef GL_GREEN_BITS
-#define GL_GREEN_BITS 0x0D53
-#endif
-#ifndef GL_HIGH_FLOAT
-#define GL_HIGH_FLOAT 0x8DF2
-#endif
-#ifndef GL_HIGH_INT
-#define GL_HIGH_INT 0x8DF5
-#endif
-#ifndef GL_IMPLEMENTATION_COLOR_READ_FORMAT
-#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B
-#endif
-#ifndef GL_IMPLEMENTATION_COLOR_READ_TYPE
-#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A
-#endif
-#ifndef GL_INCR
-#define GL_INCR 0x1E02
-#endif
-#ifndef GL_INCR_WRAP
-#define GL_INCR_WRAP 0x8507
-#endif
-#ifndef GL_INFO_LOG_LENGTH
-#define GL_INFO_LOG_LENGTH 0x8B84
-#endif
-#ifndef GL_INT
-#define GL_INT 0x1404
-#endif
-#ifndef GL_INT_VEC2
-#define GL_INT_VEC2 0x8B53
-#endif
-#ifndef GL_INT_VEC3
-#define GL_INT_VEC3 0x8B54
-#endif
-#ifndef GL_INT_VEC4
-#define GL_INT_VEC4 0x8B55
-#endif
-#ifndef GL_INVALID_ENUM
-#define GL_INVALID_ENUM 0x0500
-#endif
-#ifndef GL_INVALID_FRAMEBUFFER_OPERATION
-#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
-#endif
-#ifndef GL_INVALID_OPERATION
-#define GL_INVALID_OPERATION 0x0502
-#endif
-#ifndef GL_INVALID_VALUE
-#define GL_INVALID_VALUE 0x0501
-#endif
-#ifndef GL_INVERT
-#define GL_INVERT 0x150A
-#endif
-#ifndef GL_KEEP
-#define GL_KEEP 0x1E00
-#endif
-#ifndef GL_LEQUAL
-#define GL_LEQUAL 0x0203
-#endif
-#ifndef GL_LESS
-#define GL_LESS 0x0201
-#endif
-#ifndef GL_LINEAR
-#define GL_LINEAR 0x2601
-#endif
-#ifndef GL_LINEAR_MIPMAP_LINEAR
-#define GL_LINEAR_MIPMAP_LINEAR 0x2703
-#endif
-#ifndef GL_LINEAR_MIPMAP_NEAREST
-#define GL_LINEAR_MIPMAP_NEAREST 0x2701
-#endif
-#ifndef GL_LINE_LOOP
-#define GL_LINE_LOOP 0x0002
-#endif
-#ifndef GL_LINES
-#define GL_LINES 0x0001
-#endif
-#ifndef GL_LINE_STRIP
-#define GL_LINE_STRIP 0x0003
-#endif
-#ifndef GL_LINE_WIDTH
-#define GL_LINE_WIDTH 0x0B21
-#endif
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-#ifndef GL_LOW_FLOAT
-#define GL_LOW_FLOAT 0x8DF0
-#endif
-#ifndef GL_LOW_INT
-#define GL_LOW_INT 0x8DF3
-#endif
-#ifndef GL_LUMINANCE
-#define GL_LUMINANCE 0x1909
-#endif
-#ifndef GL_LUMINANCE_ALPHA
-#define GL_LUMINANCE_ALPHA 0x190A
-#endif
-#ifndef GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS
-#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
-#endif
-#ifndef GL_MAX_CUBE_MAP_TEXTURE_SIZE
-#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C
-#endif
-#ifndef GL_MAX_FRAGMENT_UNIFORM_VECTORS
-#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
-#endif
-#ifndef GL_MAX_RENDERBUFFER_SIZE
-#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
-#endif
-#ifndef GL_MAX_TEXTURE_IMAGE_UNITS
-#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
-#endif
-#ifndef GL_MAX_TEXTURE_SIZE
-#define GL_MAX_TEXTURE_SIZE 0x0D33
-#endif
-#ifndef GL_MAX_VARYING_VECTORS
-#define GL_MAX_VARYING_VECTORS 0x8DFC
-#endif
-#ifndef GL_MAX_VERTEX_ATTRIBS
-#define GL_MAX_VERTEX_ATTRIBS 0x8869
-#endif
-#ifndef GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS
-#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
-#endif
-#ifndef GL_MAX_VERTEX_UNIFORM_VECTORS
-#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
-#endif
-#ifndef GL_MAX_VIEWPORT_DIMS
-#define GL_MAX_VIEWPORT_DIMS 0x0D3A
-#endif
-#ifndef GL_MEDIUM_FLOAT
-#define GL_MEDIUM_FLOAT 0x8DF1
-#endif
-#ifndef GL_MEDIUM_INT
-#define GL_MEDIUM_INT 0x8DF4
-#endif
-#ifndef GL_MIRRORED_REPEAT
-#define GL_MIRRORED_REPEAT 0x8370
-#endif
-#ifndef GL_NEAREST
-#define GL_NEAREST 0x2600
-#endif
-#ifndef GL_NEAREST_MIPMAP_LINEAR
-#define GL_NEAREST_MIPMAP_LINEAR 0x2702
-#endif
-#ifndef GL_NEAREST_MIPMAP_NEAREST
-#define GL_NEAREST_MIPMAP_NEAREST 0x2700
-#endif
-#ifndef GL_NEVER
-#define GL_NEVER 0x0200
-#endif
-#ifndef GL_NICEST
-#define GL_NICEST 0x1102
-#endif
-#ifndef GL_NO_ERROR
-#define GL_NO_ERROR 0
-#endif
-#ifndef GL_NONE
-#define GL_NONE 0
-#endif
-#ifndef GL_NOTEQUAL
-#define GL_NOTEQUAL 0x0205
-#endif
-#ifndef GL_NUM_COMPRESSED_TEXTURE_FORMATS
-#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2
-#endif
-#ifndef GL_NUM_SHADER_BINARY_FORMATS
-#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
-#endif
-#ifndef GL_ONE
-#define GL_ONE 1
-#endif
-#ifndef GL_ONE_MINUS_CONSTANT_ALPHA
-#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
-#endif
-#ifndef GL_ONE_MINUS_CONSTANT_COLOR
-#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
-#endif
-#ifndef GL_ONE_MINUS_DST_ALPHA
-#define GL_ONE_MINUS_DST_ALPHA 0x0305
-#endif
-#ifndef GL_ONE_MINUS_DST_COLOR
-#define GL_ONE_MINUS_DST_COLOR 0x0307
-#endif
-#ifndef GL_ONE_MINUS_SRC_ALPHA
-#define GL_ONE_MINUS_SRC_ALPHA 0x0303
-#endif
-#ifndef GL_ONE_MINUS_SRC_COLOR
-#define GL_ONE_MINUS_SRC_COLOR 0x0301
-#endif
-#ifndef GL_OUT_OF_MEMORY
-#define GL_OUT_OF_MEMORY 0x0505
-#endif
-#ifndef GL_PACK_ALIGNMENT
-#define GL_PACK_ALIGNMENT 0x0D05
-#endif
-#ifndef GL_POINTS
-#define GL_POINTS 0x0000
-#endif
-#ifndef GL_POLYGON_OFFSET_FACTOR
-#define GL_POLYGON_OFFSET_FACTOR 0x8038
-#endif
-#ifndef GL_POLYGON_OFFSET_FILL
-#define GL_POLYGON_OFFSET_FILL 0x8037
-#endif
-#ifndef GL_POLYGON_OFFSET_UNITS
-#define GL_POLYGON_OFFSET_UNITS 0x2A00
-#endif
-#ifndef GL_RED_BITS
-#define GL_RED_BITS 0x0D52
-#endif
-#ifndef GL_RENDERBUFFER
-#define GL_RENDERBUFFER 0x8D41
-#endif
-#ifndef GL_RENDERBUFFER_ALPHA_SIZE
-#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
-#endif
-#ifndef GL_RENDERBUFFER_BINDING
-#define GL_RENDERBUFFER_BINDING 0x8CA7
-#endif
-#ifndef GL_RENDERBUFFER_BLUE_SIZE
-#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
-#endif
-#ifndef GL_RENDERBUFFER_DEPTH_SIZE
-#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
-#endif
-#ifndef GL_RENDERBUFFER_GREEN_SIZE
-#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
-#endif
-#ifndef GL_RENDERBUFFER_HEIGHT
-#define GL_RENDERBUFFER_HEIGHT 0x8D43
-#endif
-#ifndef GL_RENDERBUFFER_INTERNAL_FORMAT
-#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
-#endif
-#ifndef GL_RENDERBUFFER_RED_SIZE
-#define GL_RENDERBUFFER_RED_SIZE 0x8D50
-#endif
-#ifndef GL_RENDERBUFFER_STENCIL_SIZE
-#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
-#endif
-#ifndef GL_RENDERBUFFER_WIDTH
-#define GL_RENDERBUFFER_WIDTH 0x8D42
-#endif
-#ifndef GL_RENDERER
-#define GL_RENDERER 0x1F01
-#endif
-#ifndef GL_REPEAT
-#define GL_REPEAT 0x2901
-#endif
-#ifndef GL_REPLACE
-#define GL_REPLACE 0x1E01
-#endif
-#ifndef GL_RGB
-#define GL_RGB 0x1907
-#endif
-#ifndef GL_RGB565
-#define GL_RGB565 0x8D62
-#endif
-#ifndef GL_RGB5_A1
-#define GL_RGB5_A1 0x8057
-#endif
-#ifndef GL_RGBA
-#define GL_RGBA 0x1908
-#endif
-#ifndef GL_RGBA4
-#define GL_RGBA4 0x8056
-#endif
-#ifndef GL_BGRA
-#define GL_BGRA 0x80E1
-#endif
-#ifndef GL_SAMPLE_ALPHA_TO_COVERAGE
-#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E
-#endif
-#ifndef GL_SAMPLE_BUFFERS
-#define GL_SAMPLE_BUFFERS 0x80A8
-#endif
-#ifndef GL_SAMPLE_COVERAGE
-#define GL_SAMPLE_COVERAGE 0x80A0
-#endif
-#ifndef GL_SAMPLE_COVERAGE_INVERT
-#define GL_SAMPLE_COVERAGE_INVERT 0x80AB
-#endif
-#ifndef GL_SAMPLE_COVERAGE_VALUE
-#define GL_SAMPLE_COVERAGE_VALUE 0x80AA
-#endif
-#ifndef GL_SAMPLER_2D
-#define GL_SAMPLER_2D 0x8B5E
-#endif
-#ifndef GL_SAMPLER_CUBE
-#define GL_SAMPLER_CUBE 0x8B60
-#endif
-#ifndef GL_SAMPLES
-#define GL_SAMPLES 0x80A9
-#endif
-#ifndef GL_SCISSOR_BOX
-#define GL_SCISSOR_BOX 0x0C10
-#endif
-#ifndef GL_SCISSOR_TEST
-#define GL_SCISSOR_TEST 0x0C11
-#endif
-#ifndef GL_SHADER_BINARY_FORMATS
-#define GL_SHADER_BINARY_FORMATS 0x8DF8
-#endif
-#ifndef GL_SHADER_COMPILER
-#define GL_SHADER_COMPILER 0x8DFA
-#endif
-#ifndef GL_SHADER_SOURCE_LENGTH
-#define GL_SHADER_SOURCE_LENGTH 0x8B88
-#endif
-#ifndef GL_SHADER_TYPE
-#define GL_SHADER_TYPE 0x8B4F
-#endif
-#ifndef GL_SHADING_LANGUAGE_VERSION
-#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
-#endif
-#ifndef GL_SHORT
-#define GL_SHORT 0x1402
-#endif
-#ifndef GL_SRC_ALPHA
-#define GL_SRC_ALPHA 0x0302
-#endif
-#ifndef GL_SRC_ALPHA_SATURATE
-#define GL_SRC_ALPHA_SATURATE 0x0308
-#endif
-#ifndef GL_SRC_COLOR
-#define GL_SRC_COLOR 0x0300
-#endif
-#ifndef GL_STATIC_DRAW
-#define GL_STATIC_DRAW 0x88E4
-#endif
-#ifndef GL_STENCIL_ATTACHMENT
-#define GL_STENCIL_ATTACHMENT 0x8D20
-#endif
-#ifndef GL_STENCIL_BACK_FAIL
-#define GL_STENCIL_BACK_FAIL 0x8801
-#endif
-#ifndef GL_STENCIL_BACK_FUNC
-#define GL_STENCIL_BACK_FUNC 0x8800
-#endif
-#ifndef GL_STENCIL_BACK_PASS_DEPTH_FAIL
-#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
-#endif
-#ifndef GL_STENCIL_BACK_PASS_DEPTH_PASS
-#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
-#endif
-#ifndef GL_STENCIL_BACK_REF
-#define GL_STENCIL_BACK_REF 0x8CA3
-#endif
-#ifndef GL_STENCIL_BACK_VALUE_MASK
-#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
-#endif
-#ifndef GL_STENCIL_BACK_WRITEMASK
-#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
-#endif
-#ifndef GL_STENCIL_BITS
-#define GL_STENCIL_BITS 0x0D57
-#endif
-#ifndef GL_STENCIL_BUFFER_BIT
-#define GL_STENCIL_BUFFER_BIT 0x00000400
-#endif
-#ifndef GL_STENCIL_CLEAR_VALUE
-#define GL_STENCIL_CLEAR_VALUE 0x0B91
-#endif
-#ifndef GL_STENCIL_FAIL
-#define GL_STENCIL_FAIL 0x0B94
-#endif
-#ifndef GL_STENCIL_FUNC
-#define GL_STENCIL_FUNC 0x0B92
-#endif
-#ifndef GL_STENCIL_INDEX
-#define GL_STENCIL_INDEX 0x1901
-#endif
-#ifndef GL_STENCIL_INDEX8
-#define GL_STENCIL_INDEX8 0x8D48
-#endif
-#ifndef GL_STENCIL_PASS_DEPTH_FAIL
-#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95
-#endif
-#ifndef GL_STENCIL_PASS_DEPTH_PASS
-#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96
-#endif
-#ifndef GL_STENCIL_REF
-#define GL_STENCIL_REF 0x0B97
-#endif
-#ifndef GL_STENCIL_TEST
-#define GL_STENCIL_TEST 0x0B90
-#endif
-#ifndef GL_STENCIL_VALUE_MASK
-#define GL_STENCIL_VALUE_MASK 0x0B93
-#endif
-#ifndef GL_STENCIL_WRITEMASK
-#define GL_STENCIL_WRITEMASK 0x0B98
-#endif
-#ifndef GL_STREAM_DRAW
-#define GL_STREAM_DRAW 0x88E0
-#endif
-#ifndef GL_SUBPIXEL_BITS
-#define GL_SUBPIXEL_BITS 0x0D50
-#endif
-#ifndef GL_TEXTURE0
-#define GL_TEXTURE0 0x84C0
-#endif
-#ifndef GL_TEXTURE
-#define GL_TEXTURE 0x1702
-#endif
-#ifndef GL_TEXTURE10
-#define GL_TEXTURE10 0x84CA
-#endif
-#ifndef GL_TEXTURE1
-#define GL_TEXTURE1 0x84C1
-#endif
-#ifndef GL_TEXTURE11
-#define GL_TEXTURE11 0x84CB
-#endif
-#ifndef GL_TEXTURE12
-#define GL_TEXTURE12 0x84CC
-#endif
-#ifndef GL_TEXTURE13
-#define GL_TEXTURE13 0x84CD
-#endif
-#ifndef GL_TEXTURE14
-#define GL_TEXTURE14 0x84CE
-#endif
-#ifndef GL_TEXTURE15
-#define GL_TEXTURE15 0x84CF
-#endif
-#ifndef GL_TEXTURE16
-#define GL_TEXTURE16 0x84D0
-#endif
-#ifndef GL_TEXTURE17
-#define GL_TEXTURE17 0x84D1
-#endif
-#ifndef GL_TEXTURE18
-#define GL_TEXTURE18 0x84D2
-#endif
-#ifndef GL_TEXTURE19
-#define GL_TEXTURE19 0x84D3
-#endif
-#ifndef GL_TEXTURE20
-#define GL_TEXTURE20 0x84D4
-#endif
-#ifndef GL_TEXTURE2
-#define GL_TEXTURE2 0x84C2
-#endif
-#ifndef GL_TEXTURE21
-#define GL_TEXTURE21 0x84D5
-#endif
-#ifndef GL_TEXTURE22
-#define GL_TEXTURE22 0x84D6
-#endif
-#ifndef GL_TEXTURE23
-#define GL_TEXTURE23 0x84D7
-#endif
-#ifndef GL_TEXTURE24
-#define GL_TEXTURE24 0x84D8
-#endif
-#ifndef GL_TEXTURE25
-#define GL_TEXTURE25 0x84D9
-#endif
-#ifndef GL_TEXTURE26
-#define GL_TEXTURE26 0x84DA
-#endif
-#ifndef GL_TEXTURE27
-#define GL_TEXTURE27 0x84DB
-#endif
-#ifndef GL_TEXTURE28
-#define GL_TEXTURE28 0x84DC
-#endif
-#ifndef GL_TEXTURE29
-#define GL_TEXTURE29 0x84DD
-#endif
-#ifndef GL_TEXTURE_2D
-#define GL_TEXTURE_2D 0x0DE1
-#endif
-#ifndef GL_TEXTURE30
-#define GL_TEXTURE30 0x84DE
-#endif
-#ifndef GL_TEXTURE3
-#define GL_TEXTURE3 0x84C3
-#endif
-#ifndef GL_TEXTURE31
-#define GL_TEXTURE31 0x84DF
-#endif
-#ifndef GL_TEXTURE4
-#define GL_TEXTURE4 0x84C4
-#endif
-#ifndef GL_TEXTURE5
-#define GL_TEXTURE5 0x84C5
-#endif
-#ifndef GL_TEXTURE6
-#define GL_TEXTURE6 0x84C6
-#endif
-#ifndef GL_TEXTURE7
-#define GL_TEXTURE7 0x84C7
-#endif
-#ifndef GL_TEXTURE8
-#define GL_TEXTURE8 0x84C8
-#endif
-#ifndef GL_TEXTURE9
-#define GL_TEXTURE9 0x84C9
-#endif
-#ifndef GL_TEXTURE_BINDING_2D
-#define GL_TEXTURE_BINDING_2D 0x8069
-#endif
-#ifndef GL_TEXTURE_BINDING_CUBE_MAP
-#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP
-#define GL_TEXTURE_CUBE_MAP 0x8513
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_X
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
-#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_X
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Y
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
-#endif
-#ifndef GL_TEXTURE_CUBE_MAP_POSITIVE_Z
-#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
-#endif
-#ifndef GL_TEXTURE_MAG_FILTER
-#define GL_TEXTURE_MAG_FILTER 0x2800
-#endif
-#ifndef GL_TEXTURE_MIN_FILTER
-#define GL_TEXTURE_MIN_FILTER 0x2801
-#endif
-#ifndef GL_TEXTURE_WRAP_S
-#define GL_TEXTURE_WRAP_S 0x2802
-#endif
-#ifndef GL_TEXTURE_WRAP_T
-#define GL_TEXTURE_WRAP_T 0x2803
-#endif
-#ifndef GL_TRIANGLE_FAN
-#define GL_TRIANGLE_FAN 0x0006
-#endif
-#ifndef GL_TRIANGLES
-#define GL_TRIANGLES 0x0004
-#endif
-#ifndef GL_TRIANGLE_STRIP
-#define GL_TRIANGLE_STRIP 0x0005
-#endif
-#ifndef GL_TRUE
-#define GL_TRUE 1
-#endif
-#ifndef GL_UNPACK_ALIGNMENT
-#define GL_UNPACK_ALIGNMENT 0x0CF5
-#endif
-#ifndef GL_UNSIGNED_BYTE
-#define GL_UNSIGNED_BYTE 0x1401
-#endif
-#ifndef GL_UNSIGNED_INT
-#define GL_UNSIGNED_INT 0x1405
-#endif
-#ifndef GL_UNSIGNED_SHORT
-#define GL_UNSIGNED_SHORT 0x1403
-#endif
-#ifndef GL_UNSIGNED_SHORT_4_4_4_4
-#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
-#endif
-#ifndef GL_UNSIGNED_SHORT_5_5_5_1
-#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
-#endif
-#ifndef GL_UNSIGNED_SHORT_5_6_5
-#define GL_UNSIGNED_SHORT_5_6_5 0x8363
-#endif
-#ifndef GL_VALIDATE_STATUS
-#define GL_VALIDATE_STATUS 0x8B83
-#endif
-#ifndef GL_VENDOR
-#define GL_VENDOR 0x1F00
-#endif
-#ifndef GL_VERSION
-#define GL_VERSION 0x1F02
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING
-#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_ENABLED
-#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_NORMALIZED
-#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_POINTER
-#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_SIZE
-#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_STRIDE
-#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
-#endif
-#ifndef GL_VERTEX_ATTRIB_ARRAY_TYPE
-#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
-#endif
-#ifndef GL_VERTEX_SHADER
-#define GL_VERTEX_SHADER 0x8B31
-#endif
-#ifndef GL_VIEWPORT
-#define GL_VIEWPORT 0x0BA2
-#endif
-#ifndef GL_ZERO
-#define GL_ZERO 0
-#endif
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
deleted file mode 100644
index c5151f66bb..0000000000
--- a/src/opengl/qglpaintdevice.cpp
+++ /dev/null
@@ -1,239 +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 <private/qglpaintdevice_p.h>
-#include <private/qgl_p.h>
-#include <private/qglpixelbuffer_p.h>
-#include <private/qglframebufferobject_p.h>
-#include <qopenglfunctions.h>
-#include <qwindow.h>
-
-QT_BEGIN_NAMESPACE
-
-QGLPaintDevice::QGLPaintDevice()
- : m_thisFBO(0)
-{
-}
-
-QGLPaintDevice::~QGLPaintDevice()
-{
-}
-
-int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
-{
- switch(metric) {
- case PdmWidth:
- return size().width();
- case PdmHeight:
- return size().height();
- case PdmDepth: {
- const QGLFormat f = format();
- return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
- }
- case PdmDevicePixelRatio:
- return 1;
- case PdmDevicePixelRatioScaled:
- return 1 * QPaintDevice::devicePixelRatioFScale();
- default:
- qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
- return 0;
- }
-}
-
-void QGLPaintDevice::beginPaint()
-{
- // Make sure our context is the current one:
- QGLContext *ctx = context();
- ctx->makeCurrent();
-
- ctx->d_func()->refreshCurrentFbo();
-
- // Record the currently bound FBO so we can restore it again
- // in endPaint() and bind this device's FBO
- //
- // Note: m_thisFBO could be zero if the paint device is not
- // backed by an FBO (e.g. window back buffer). But there could
- // be a previous FBO bound to the context which we need to
- // explicitly unbind. Otherwise the painting will go into
- // the previous FBO instead of to the window.
- m_previousFBO = ctx->d_func()->current_fbo;
-
- if (m_previousFBO != m_thisFBO) {
- ctx->d_func()->setCurrentFbo(m_thisFBO);
- ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
- }
-
- // Set the default fbo for the context to m_thisFBO so that
- // if some raw GL code between beginNativePainting() and
- // endNativePainting() calls QGLFramebufferObject::release(),
- // painting will revert to the window surface's fbo.
- ctx->d_ptr->default_fbo = m_thisFBO;
-}
-
-void QGLPaintDevice::ensureActiveTarget()
-{
- QGLContext* ctx = context();
- if (ctx != QGLContext::currentContext())
- ctx->makeCurrent();
-
- ctx->d_func()->refreshCurrentFbo();
-
- if (ctx->d_ptr->current_fbo != m_thisFBO) {
- ctx->d_func()->setCurrentFbo(m_thisFBO);
- ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
- }
-
- ctx->d_ptr->default_fbo = m_thisFBO;
-}
-
-void QGLPaintDevice::endPaint()
-{
- // Make sure the FBO bound at beginPaint is re-bound again here:
- QGLContext *ctx = context();
- ctx->makeCurrent();
-
- ctx->d_func()->refreshCurrentFbo();
-
- if (m_previousFBO != ctx->d_func()->current_fbo) {
- ctx->d_func()->setCurrentFbo(m_previousFBO);
- ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO);
- }
-
- ctx->d_ptr->default_fbo = 0;
-}
-
-QGLFormat QGLPaintDevice::format() const
-{
- return context()->format();
-}
-
-bool QGLPaintDevice::alphaRequested() const
-{
- return context()->d_func()->reqFormat.alpha();
-}
-
-bool QGLPaintDevice::isFlipped() const
-{
- return false;
-}
-
-////////////////// QGLWidgetGLPaintDevice //////////////////
-
-QGLWidgetGLPaintDevice::QGLWidgetGLPaintDevice()
-{
-}
-
-QPaintEngine* QGLWidgetGLPaintDevice::paintEngine() const
-{
- return glWidget->paintEngine();
-}
-
-void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w)
-{
- glWidget = w;
-}
-
-void QGLWidgetGLPaintDevice::beginPaint()
-{
- QGLPaintDevice::beginPaint();
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
- if (!glWidget->d_func()->disable_clear_on_painter_begin && glWidget->autoFillBackground()) {
- if (glWidget->testAttribute(Qt::WA_TranslucentBackground))
- funcs->glClearColor(0.0, 0.0, 0.0, 0.0);
- else {
- const QColor &c = glWidget->palette().brush(glWidget->backgroundRole()).color();
- float alpha = c.alphaF();
- funcs->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
- }
- if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
- funcs->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- else
- funcs->glClear(GL_COLOR_BUFFER_BIT);
- }
-}
-
-void QGLWidgetGLPaintDevice::endPaint()
-{
- if (glWidget->autoBufferSwap())
- glWidget->swapBuffers();
- QGLPaintDevice::endPaint();
-}
-
-
-QSize QGLWidgetGLPaintDevice::size() const
-{
- return glWidget->size() * (glWidget->windowHandle() ?
- glWidget->windowHandle()->devicePixelRatio() : qApp->devicePixelRatio());
-}
-
-QGLContext* QGLWidgetGLPaintDevice::context() const
-{
- return const_cast<QGLContext*>(glWidget->context());
-}
-
-// returns the QGLPaintDevice for the given QPaintDevice
-QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd)
-{
- QGLPaintDevice* glpd = 0;
-
- switch(pd->devType()) {
- case QInternal::Widget:
- // Should not be called on a non-gl widget:
- Q_ASSERT(qobject_cast<QGLWidget*>(static_cast<QWidget*>(pd)));
- glpd = &(static_cast<QGLWidget*>(pd)->d_func()->glDevice);
- break;
- case QInternal::Pbuffer:
- glpd = &(static_cast<QGLPixelBuffer*>(pd)->d_func()->glDevice);
- break;
- case QInternal::FramebufferObject:
- glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice);
- break;
- case QInternal::Pixmap: {
- qWarning("Pixmap type not supported for GL rendering");
- break;
- }
- default:
- qWarning("QGLPaintDevice::getDevice() - Unknown device type %d", pd->devType());
- break;
- }
-
- return glpd;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
deleted file mode 100644
index e2f434ac3c..0000000000
--- a/src/opengl/qglpixelbuffer.cpp
+++ /dev/null
@@ -1,654 +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$
-**
-****************************************************************************/
-
-/*!
- \class QGLPixelBuffer
- \inmodule QtOpenGL
- \brief The QGLPixelBuffer class encapsulates an OpenGL pbuffer.
- \since 4.1
- \obsolete
-
- \ingroup painting-3D
-
- Rendering into a pbuffer is normally done using full hardware
- acceleration. This can be significantly faster than rendering
- into a QPixmap.
-
- There are three approaches to using this class:
-
- \list 1
- \li \b{We can draw into the pbuffer and convert it to a QImage
- using toImage().} This is normally much faster than calling
- QGLWidget::renderPixmap().
-
- \li \b{We can draw into the pbuffer and copy the contents into
- an OpenGL texture using updateDynamicTexture().} This allows
- us to create dynamic textures and works on all systems
- with pbuffer support.
-
- \li \b{On systems that support it, we can bind the pbuffer to
- an OpenGL texture.} The texture is then updated automatically
- when the pbuffer contents change, eliminating the need for
- additional copy operations. This is supported only on Windows
- and \macos systems that provide the \c render_texture
- extension. Note that under Windows, a multi-sampled pbuffer
- can't be used in conjunction with the \c render_texture
- extension. If a multi-sampled pbuffer is requested under
- Windows, the \c render_texture extension is turned off for that
- pbuffer.
-
-
- \endlist
-
- \note This class has been deprecated, use QOpenGLFramebufferObject
- for offscreen rendering.
-
- \section1 Threading
-
- As of Qt 4.8, it's possible to render into a QGLPixelBuffer using
- a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES
- 2.0 is required for this to work.
-
- Pbuffers are provided by the OpenGL \c pbuffer extension; call
- hasOpenGLPbuffer() to find out if the system provides pbuffers.
-*/
-
-#include <private/qopenglextensions_p.h>
-
-#include <QtCore/qglobal.h>
-#include <QtGui/qopenglframebufferobject.h>
-
-#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
-
-#include <qglframebufferobject.h>
-#include <qglpixelbuffer.h>
-#include <private/qglpixelbuffer_p.h>
-#include <private/qfont_p.h>
-#include <qimage.h>
-
-QT_BEGIN_NAMESPACE
-
-extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);
-
-
-QGLContext* QGLPBufferGLPaintDevice::context() const
-{
- return pbuf->d_func()->qctx;
-}
-
-void QGLPBufferGLPaintDevice::beginPaint()
-{
- pbuf->makeCurrent();
- QGLPaintDevice::beginPaint();
-}
-
-void QGLPBufferGLPaintDevice::endPaint()
-{
- QOpenGLContext::currentContext()->functions()->glFlush();
- QGLPaintDevice::endPaint();
-}
-
-void QGLPBufferGLPaintDevice::setFbo(GLuint fbo)
-{
- m_thisFBO = fbo;
-}
-
-void QGLPBufferGLPaintDevice::setPBuffer(QGLPixelBuffer* pb)
-{
- pbuf = pb;
-}
-
-void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
-{
- Q_Q(QGLPixelBuffer);
- if(init(size, format, shareWidget)) {
- req_size = size;
- req_format = format;
- req_shareWidget = shareWidget;
- invalid = false;
- glDevice.setPBuffer(q);
- }
-}
-
-/*!
- Constructs an OpenGL pbuffer of the given \a size. If no \a
- format is specified, the \l{QGLFormat::defaultFormat()}{default
- format} is used. If the \a shareWidget parameter points to a
- valid QGLWidget, the pbuffer will share its context with \a
- shareWidget.
-
- If you intend to bind this pbuffer as a dynamic texture, the width
- and height components of \c size must be powers of two (e.g., 512
- x 128).
-
- \sa size(), format()
-*/
-QGLPixelBuffer::QGLPixelBuffer(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
- : d_ptr(new QGLPixelBufferPrivate(this))
-{
- Q_D(QGLPixelBuffer);
- d->common_init(size, format, shareWidget);
-}
-
-
-/*! \overload
-
- Constructs an OpenGL pbuffer with the \a width and \a height. If
- no \a format is specified, the
- \l{QGLFormat::defaultFormat()}{default format} is used. If the \a
- shareWidget parameter points to a valid QGLWidget, the pbuffer
- will share its context with \a shareWidget.
-
- If you intend to bind this pbuffer as a dynamic texture, the width
- and height components of \c size must be powers of two (e.g., 512
- x 128).
-
- \sa size(), format()
-*/
-QGLPixelBuffer::QGLPixelBuffer(int width, int height, const QGLFormat &format, QGLWidget *shareWidget)
- : d_ptr(new QGLPixelBufferPrivate(this))
-{
- Q_D(QGLPixelBuffer);
- d->common_init(QSize(width, height), format, shareWidget);
-}
-
-
-/*! \fn QGLPixelBuffer::~QGLPixelBuffer()
-
- Destroys the pbuffer and frees any allocated resources.
-*/
-QGLPixelBuffer::~QGLPixelBuffer()
-{
- Q_D(QGLPixelBuffer);
-
- // defined in qpaintengine_opengl.cpp
- QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
- if (current != d->qctx)
- makeCurrent();
- d->cleanup();
- if (current && current != d->qctx)
- current->makeCurrent();
-}
-
-/*! \fn bool QGLPixelBuffer::makeCurrent()
-
- Makes this pbuffer the current OpenGL rendering context. Returns
- true on success; otherwise returns \c false.
-
- \sa QGLContext::makeCurrent(), doneCurrent()
-*/
-
-bool QGLPixelBuffer::makeCurrent()
-{
- Q_D(QGLPixelBuffer);
- if (d->invalid)
- return false;
- d->qctx->makeCurrent();
- if (!d->fbo) {
- QOpenGLFramebufferObjectFormat format;
- if (d->req_format.stencil())
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- else if (d->req_format.depth())
- format.setAttachment(QOpenGLFramebufferObject::Depth);
- if (d->req_format.sampleBuffers())
- format.setSamples(d->req_format.samples());
- d->fbo = new QOpenGLFramebufferObject(d->req_size, format);
- d->fbo->bind();
- d->glDevice.setFbo(d->fbo->handle());
- QOpenGLContext::currentContext()->functions()->glViewport(0, 0, d->req_size.width(), d->req_size.height());
- }
- return true;
-}
-
-/*! \fn bool QGLPixelBuffer::doneCurrent()
-
- Makes no context the current OpenGL context. Returns \c true on
- success; otherwise returns \c false.
-*/
-
-bool QGLPixelBuffer::doneCurrent()
-{
- Q_D(QGLPixelBuffer);
- if (d->invalid)
- return false;
- d->qctx->doneCurrent();
- return true;
-}
-
-/*!
- Returns the context of this pixelbuffer.
-*/
-QGLContext *QGLPixelBuffer::context() const
-{
- Q_D(const QGLPixelBuffer);
- return d->qctx;
-}
-
-/*!
- \fn GLuint QGLPixelBuffer::generateDynamicTexture() const
-
- Generates and binds a 2D GL texture that is the same size as the
- pbuffer, and returns the texture's ID. This can be used in
- conjunction with bindToDynamicTexture() and
- updateDynamicTexture().
-
- \sa size()
-*/
-
-/*! \fn bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
-
- Binds the texture specified by \a texture_id to this pbuffer.
- Returns \c true on success; otherwise returns \c false.
-
- The texture must be of the same size and format as the pbuffer.
-
- To unbind the texture, call releaseFromDynamicTexture(). While
- the texture is bound, it is updated automatically when the
- pbuffer contents change, eliminating the need for additional copy
- operations.
-
- Example:
-
- \snippet code/src_opengl_qglpixelbuffer.cpp 0
-
- \warning This function uses the \c {render_texture} extension,
- which is currently not supported under X11. An alternative that
- works on all systems (including X11) is to manually copy the
- pbuffer contents to a texture using updateDynamicTexture().
-
- \warning For the bindToDynamicTexture() call to succeed on the
- \macos, the pbuffer needs a shared context, i.e. the
- QGLPixelBuffer must be created with a share widget.
-
- \sa generateDynamicTexture(), releaseFromDynamicTexture()
-*/
-
-/*! \fn void QGLPixelBuffer::releaseFromDynamicTexture()
-
- Releases the pbuffer from any previously bound texture.
-
- \sa bindToDynamicTexture()
-*/
-
-/*! \fn bool QGLPixelBuffer::hasOpenGLPbuffers()
-
- Returns \c true if the OpenGL \c pbuffer extension is present on
- this system; otherwise returns \c false.
-*/
-
-/*!
- Copies the pbuffer contents into the texture specified with \a
- texture_id.
-
- The texture must be of the same size and format as the pbuffer.
-
- Example:
-
- \snippet code/src_opengl_qglpixelbuffer.cpp 1
-
- An alternative on Windows and \macos systems that support the
- \c render_texture extension is to use bindToDynamicTexture() to
- get dynamic updates of the texture.
-
- \sa generateDynamicTexture(), bindToDynamicTexture()
-*/
-void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
-{
- Q_D(const QGLPixelBuffer);
- if (d->invalid || !d->fbo)
- return;
-
- const QGLContext *ctx = QGLContext::currentContext();
- if (!ctx)
- return;
-
-#undef glBindFramebuffer
-
-#ifndef GL_READ_FRAMEBUFFER
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#endif
-
-#ifndef GL_DRAW_FRAMEBUFFER
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#endif
-
- QOpenGLExtensions extensions(ctx->contextHandle());
-
- ctx->d_ptr->refreshCurrentFbo();
-
- if (d->blit_fbo) {
- QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
- extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());
- }
-
- extensions.glBindTexture(GL_TEXTURE_2D, texture_id);
-#ifndef QT_OPENGL_ES
- GLenum format = ctx->contextHandle()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
- extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, d->req_size.width(), d->req_size.height(), 0);
-#else
- extensions.glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
-#endif
-
- if (d->blit_fbo)
- extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->d_func()->current_fbo);
-}
-
-/*!
- Returns the size of the pbuffer.
-*/
-QSize QGLPixelBuffer::size() const
-{
- Q_D(const QGLPixelBuffer);
- return d->req_size;
-}
-
-/*!
- Returns the contents of the pbuffer as a QImage.
-*/
-QImage QGLPixelBuffer::toImage() const
-{
- Q_D(const QGLPixelBuffer);
- if (d->invalid)
- return QImage();
-
- const_cast<QGLPixelBuffer *>(this)->makeCurrent();
- if (d->fbo)
- d->fbo->bind();
- return qt_gl_read_frame_buffer(d->req_size, d->format.alpha(), true);
-}
-
-/*!
- Returns the native pbuffer handle.
-*/
-Qt::HANDLE QGLPixelBuffer::handle() const
-{
- Q_D(const QGLPixelBuffer);
- if (d->invalid)
- return 0;
- return (Qt::HANDLE) d->pbuf;
-}
-
-/*!
- Returns \c true if this pbuffer is valid; otherwise returns \c false.
-*/
-bool QGLPixelBuffer::isValid() const
-{
- Q_D(const QGLPixelBuffer);
- return !d->invalid;
-}
-
-Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine)
-
-/*! \reimp */
-QPaintEngine *QGLPixelBuffer::paintEngine() const
-{
- return qt_buffer_2_engine()->engine();
-}
-
-/*! \reimp */
-int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
-{
- Q_D(const QGLPixelBuffer);
-
- float dpmx = qt_defaultDpiX()*100./2.54;
- float dpmy = qt_defaultDpiY()*100./2.54;
- int w = d->req_size.width();
- int h = d->req_size.height();
- switch (metric) {
- case PdmWidth:
- return w;
-
- case PdmHeight:
- return h;
-
- case PdmWidthMM:
- return qRound(w * 1000 / dpmx);
-
- case PdmHeightMM:
- return qRound(h * 1000 / dpmy);
-
- case PdmNumColors:
- return 0;
-
- case PdmDepth:
- return 32;//d->depth;
-
- case PdmDpiX:
- return qRound(dpmx * 0.0254);
-
- case PdmDpiY:
- return qRound(dpmy * 0.0254);
-
- case PdmPhysicalDpiX:
- return qRound(dpmx * 0.0254);
-
- case PdmPhysicalDpiY:
- return qRound(dpmy * 0.0254);
-
- case QPaintDevice::PdmDevicePixelRatio:
- return 1;
-
- case QPaintDevice::PdmDevicePixelRatioScaled:
- return QPaintDevice::devicePixelRatioFScale();
-
- default:
- qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
- break;
- }
- return 0;
-}
-
-/*!
- Generates and binds a 2D GL texture to the current context, based
- on \a image. The generated texture id is returned and can be used
- in later glBindTexture() calls.
-
- The \a target parameter specifies the texture target.
-
- Equivalent to calling QGLContext::bindTexture().
-
- \sa deleteTexture()
-*/
-GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target)
-{
- Q_D(QGLPixelBuffer);
-#ifndef QT_OPENGL_ES
- GLenum format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
- return d->qctx->bindTexture(image, target, GLint(format));
-#else
- return d->qctx->bindTexture(image, target, GL_RGBA);
-#endif
-}
-
-/*! \overload
-
- Generates and binds a 2D GL texture based on \a pixmap.
-
- Equivalent to calling QGLContext::bindTexture().
-
- \sa deleteTexture()
-*/
-GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target)
-{
- Q_D(QGLPixelBuffer);
-#ifndef QT_OPENGL_ES
- GLenum format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
- return d->qctx->bindTexture(pixmap, target, GLint(format));
-#else
- return d->qctx->bindTexture(pixmap, target, GL_RGBA);
-#endif
-}
-
-/*! \overload
-
- Reads the DirectDrawSurface (DDS) compressed file \a fileName and
- generates a 2D GL texture from it.
-
- Equivalent to calling QGLContext::bindTexture().
-
- \sa deleteTexture()
-*/
-GLuint QGLPixelBuffer::bindTexture(const QString &fileName)
-{
- Q_D(QGLPixelBuffer);
- return d->qctx->bindTexture(fileName);
-}
-
-/*!
- Removes the texture identified by \a texture_id from the texture cache.
-
- Equivalent to calling QGLContext::deleteTexture().
- */
-void QGLPixelBuffer::deleteTexture(GLuint texture_id)
-{
- Q_D(QGLPixelBuffer);
- d->qctx->deleteTexture(texture_id);
-}
-
-/*!
- \since 4.4
-
- Draws the given texture, \a textureId, to the given target rectangle,
- \a target, in OpenGL model space. The \a textureTarget should be a 2D
- texture target.
-
- Equivalent to the corresponding QGLContext::drawTexture().
-*/
-void QGLPixelBuffer::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
-{
- Q_D(QGLPixelBuffer);
- d->qctx->drawTexture(target, textureId, textureTarget);
-}
-
-/*!
- \since 4.4
-
- Draws the given texture, \a textureId, at the given \a point in OpenGL model
- space. The textureTarget parameter should be a 2D texture target.
-
- Equivalent to the corresponding QGLContext::drawTexture().
-*/
-void QGLPixelBuffer::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
-{
- Q_D(QGLPixelBuffer);
- d->qctx->drawTexture(point, textureId, textureTarget);
-}
-
-/*!
- Returns the format of the pbuffer. The format may be different
- from the one that was requested.
-*/
-QGLFormat QGLPixelBuffer::format() const
-{
- Q_D(const QGLPixelBuffer);
- return d->format;
-}
-
-/*! \fn int QGLPixelBuffer::devType() const
- \internal
-*/
-
-bool QGLPixelBufferPrivate::init(const QSize &, const QGLFormat &f, QGLWidget *shareWidget)
-{
- widget = new QGLWidget(f, 0, shareWidget);
- widget->resize(1, 1);
- qctx = const_cast<QGLContext *>(widget->context());
- return widget->isValid();
-}
-
-bool QGLPixelBufferPrivate::cleanup()
-{
- delete fbo;
- fbo = 0;
- delete blit_fbo;
- blit_fbo = 0;
- delete widget;
- widget = 0;
- return true;
-}
-
-bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
-{
- Q_UNUSED(texture_id);
- return false;
-}
-
-void QGLPixelBuffer::releaseFromDynamicTexture()
-{
-}
-
-GLuint QGLPixelBuffer::generateDynamicTexture() const
-{
- Q_D(const QGLPixelBuffer);
- if (!d->fbo)
- return 0;
-
- if (d->fbo->format().samples() > 0
- && QOpenGLExtensions(QOpenGLContext::currentContext())
- .hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
- {
- if (!d->blit_fbo)
- const_cast<QOpenGLFramebufferObject *&>(d->blit_fbo) = new QOpenGLFramebufferObject(d->req_size);
- } else {
- return d->fbo->texture();
- }
-
- GLuint texture;
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
-
- funcs->glGenTextures(1, &texture);
- funcs->glBindTexture(GL_TEXTURE_2D, texture);
-
- 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);
-
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
- return texture;
-}
-
-bool QGLPixelBuffer::hasOpenGLPbuffers()
-{
- return QGLFramebufferObject::hasOpenGLFramebufferObjects();
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglpixelbuffer.h b/src/opengl/qglpixelbuffer.h
deleted file mode 100644
index f5d7929c35..0000000000
--- a/src/opengl/qglpixelbuffer.h
+++ /dev/null
@@ -1,104 +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 QGLPIXELBUFFER_H
-#define QGLPIXELBUFFER_H
-
-#include <QtOpenGL/qgl.h>
-#include <QtGui/qpaintdevice.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLPixelBufferPrivate;
-
-class Q_OPENGL_EXPORT QGLPixelBuffer : public QPaintDevice
-{
- Q_DECLARE_PRIVATE(QGLPixelBuffer)
-public:
- QGLPixelBuffer(const QSize &size, const QGLFormat &format = QGLFormat::defaultFormat(),
- QGLWidget *shareWidget = nullptr);
- QGLPixelBuffer(int width, int height, const QGLFormat &format = QGLFormat::defaultFormat(),
- QGLWidget *shareWidget = nullptr);
- virtual ~QGLPixelBuffer();
-
- bool isValid() const;
- bool makeCurrent();
- bool doneCurrent();
-
- QGLContext *context() const;
-
- GLuint generateDynamicTexture() const;
- bool bindToDynamicTexture(GLuint texture);
- void releaseFromDynamicTexture();
- void updateDynamicTexture(GLuint texture_id) const;
-
- GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D);
- GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D);
- GLuint bindTexture(const QString &fileName);
- void deleteTexture(GLuint texture_id);
-
- void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
- void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
-
- QSize size() const;
- Qt::HANDLE handle() const;
- QImage toImage() const;
-
- QPaintEngine *paintEngine() const override;
- QGLFormat format() const;
-
- static bool hasOpenGLPbuffers();
-
-protected:
- int metric(PaintDeviceMetric metric) const override;
- int devType() const override { return QInternal::Pbuffer; }
-
-private:
- Q_DISABLE_COPY(QGLPixelBuffer)
- QScopedPointer<QGLPixelBufferPrivate> d_ptr;
- friend class QGLDrawable;
- friend class QGLPaintDevice;
- friend class QGLPBufferGLPaintDevice;
- friend class QGLContextPrivate;
-};
-
-QT_END_NAMESPACE
-
-#endif // QGLPIXELBUFFER_H
diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h
deleted file mode 100644
index 2729ade2b6..0000000000
--- a/src/opengl/qglpixelbuffer_p.h
+++ /dev/null
@@ -1,107 +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 QGLPIXELBUFFER_P_H
-#define QGLPIXELBUFFER_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 "QtOpenGL/qglpixelbuffer.h"
-#include <private/qgl_p.h>
-#include <private/qglpaintdevice_p.h>
-
-QT_BEGIN_NAMESPACE
-
-class QEglContext;
-class QOpenGLFramebufferObject;
-
-class QGLPBufferGLPaintDevice : public QGLPaintDevice
-{
-public:
- QPaintEngine* paintEngine() const override {return pbuf->paintEngine();}
- QSize size() const override {return pbuf->size();}
- QGLContext* context() const override;
- void beginPaint() override;
- void endPaint() override;
- void setPBuffer(QGLPixelBuffer* pb);
- void setFbo(GLuint fbo);
-private:
- QGLPixelBuffer* pbuf;
-};
-
-class QGLPixelBufferPrivate {
- Q_DECLARE_PUBLIC(QGLPixelBuffer)
-public:
- QGLPixelBufferPrivate(QGLPixelBuffer *q) : q_ptr(q), invalid(true), qctx(nullptr), widget(nullptr), fbo(nullptr), blit_fbo(nullptr), pbuf(nullptr), ctx(nullptr)
- {
- }
- bool init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget);
- void common_init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget);
- bool cleanup();
-
- QGLPixelBuffer *q_ptr;
- bool invalid;
- QGLContext *qctx;
- QGLPBufferGLPaintDevice glDevice;
- QGLWidget *widget;
- QOpenGLFramebufferObject *fbo;
- QOpenGLFramebufferObject *blit_fbo;
- QGLFormat format;
-
- QGLFormat req_format;
- QPointer<QGLWidget> req_shareWidget;
- QSize req_size;
-
- //stubs
- void *pbuf;
- void *ctx;
-};
-
-QT_END_NAMESPACE
-
-#endif // QGLPIXELBUFFER_P_H
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
deleted file mode 100644
index 35f60318be..0000000000
--- a/src/opengl/qglshaderprogram.cpp
+++ /dev/null
@@ -1,3237 +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 "qglshaderprogram.h"
-#include <private/qopenglextensions_p.h>
-#include "qgl_p.h"
-#include <QtCore/private/qobject_p.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qfile.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtCore/qvector.h>
-#include <QDebug>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QGLShaderProgram
- \inmodule QtOpenGL
- \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
- \since 4.6
- \obsolete
- \ingroup painting-3D
-
- \section1 Introduction
-
- This class supports shader programs written in the OpenGL Shading
- Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
-
- QGLShader and QGLShaderProgram shelter the programmer from the details of
- compiling and linking vertex and fragment shaders.
-
- The following example creates a vertex shader program using the
- supplied source \c{code}. Once compiled and linked, the shader
- program is activated in the current QGLContext by calling
- QGLShaderProgram::bind():
-
- \snippet code/src_opengl_qglshaderprogram.cpp 0
-
- \section1 Writing Portable Shaders
-
- Shader programs can be difficult to reuse across OpenGL implementations
- because of varying levels of support for standard vertex attributes and
- uniform variables. In particular, GLSL/ES lacks all of the
- standard variables that are present on desktop OpenGL systems:
- \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
- lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
-
- The QGLShaderProgram class makes the process of writing portable shaders
- easier by prefixing all shader programs with the following lines on
- desktop OpenGL:
-
- \code
- #define highp
- #define mediump
- #define lowp
- \endcode
-
- This makes it possible to run most GLSL/ES shader programs
- on desktop systems. The programmer should restrict themselves
- to just features that are present in GLSL/ES, and avoid
- standard variable names that only work on the desktop.
-
- \section1 Simple Shader Example
-
- \snippet code/src_opengl_qglshaderprogram.cpp 1
-
- With the above shader program active, we can draw a green triangle
- as follows:
-
- \snippet code/src_opengl_qglshaderprogram.cpp 2
-
- \section1 Binary Shaders and Programs
-
- Binary shaders may be specified using \c{glShaderBinary()} on
- the return value from QGLShader::shaderId(). The QGLShader instance
- containing the binary can then be added to the shader program with
- addShader() and linked in the usual fashion with link().
-
- Binary programs may be specified using \c{glProgramBinaryOES()}
- on the return value from programId(). Then the application should
- call link(), which will notice that the program has already been
- specified and linked, allowing other operations to be performed
- on the shader program.
-
- \note This class has been deprecated in favor of QOpenGLShaderProgram.
-
- \sa QGLShader
-*/
-
-/*!
- \class QGLShader
- \inmodule QtOpenGL
- \brief The QGLShader class allows OpenGL shaders to be compiled.
- \since 4.6
- \obsolete
- \ingroup painting-3D
-
- This class supports shaders written in the OpenGL Shading Language (GLSL)
- and in the OpenGL/ES Shading Language (GLSL/ES).
-
- QGLShader and QGLShaderProgram shelter the programmer from the details of
- compiling and linking vertex and fragment shaders.
-
- \note This class has been deprecated in favor of QOpenGLShader.
-
- \sa QGLShaderProgram
-*/
-
-/*!
- \enum QGLShader::ShaderTypeBit
- This enum specifies the type of QGLShader that is being created.
-
- \value Vertex Vertex shader written in the OpenGL Shading Language (GLSL).
- \value Fragment Fragment shader written in the OpenGL Shading Language (GLSL).
- \value Geometry Geometry shaders written in the OpenGL Shading
- Language (GLSL), based on the GL_EXT_geometry_shader4 extension.
-*/
-
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-#ifndef GL_VERTEX_SHADER
-#define GL_VERTEX_SHADER 0x8B31
-#endif
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-#ifndef GL_INFO_LOG_LENGTH
-#define GL_INFO_LOG_LENGTH 0x8B84
-#endif
-#ifndef GL_ACTIVE_UNIFORMS
-#define GL_ACTIVE_UNIFORMS 0x8B86
-#endif
-#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
-#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
-#endif
-#ifndef GL_ACTIVE_ATTRIBUTES
-#define GL_ACTIVE_ATTRIBUTES 0x8B89
-#endif
-#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
-#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
-#endif
-#ifndef GL_CURRENT_VERTEX_ATTRIB
-#define GL_CURRENT_VERTEX_ATTRIB 0x8626
-#endif
-#ifndef GL_SHADER_SOURCE_LENGTH
-#define GL_SHADER_SOURCE_LENGTH 0x8B88
-#endif
-#ifndef GL_SHADER_BINARY_FORMATS
-#define GL_SHADER_BINARY_FORMATS 0x8DF8
-#endif
-#ifndef GL_NUM_SHADER_BINARY_FORMATS
-#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
-#endif
-
-class QGLShaderPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QGLShader)
-public:
- QGLShaderPrivate(const QGLContext *ctx, QGLShader::ShaderType type)
- : shaderGuard(0)
- , shaderType(type)
- , compiled(false)
- , glfuncs(new QOpenGLFunctions(ctx->contextHandle()))
- {
- }
- ~QGLShaderPrivate();
-
- QGLSharedResourceGuardBase *shaderGuard;
- QGLShader::ShaderType shaderType;
- bool compiled;
- QString log;
-
- QOpenGLFunctions *glfuncs;
-
- bool create();
- bool compile(QGLShader *q);
- void deleteShader();
-};
-
-namespace {
- void freeShaderFunc(QGLContext *ctx, GLuint id)
- {
- Q_ASSERT(ctx);
- ctx->contextHandle()->functions()->glDeleteShader(id);
- }
-}
-
-#define ctx QGLContext::currentContext()
-
-QGLShaderPrivate::~QGLShaderPrivate()
-{
- delete glfuncs;
- if (shaderGuard)
- shaderGuard->free();
-}
-
-bool QGLShaderPrivate::create()
-{
- QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext());
- if (!context)
- return false;
-
- if (glfuncs->hasOpenGLFeature(QOpenGLFunctions::Shaders)) {
- GLuint shader;
- if (shaderType == QGLShader::Vertex)
- shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
-#if !defined(QT_OPENGL_ES_2)
- else if (shaderType == QGLShader::Geometry
- && !context->contextHandle()->isOpenGLES())
- shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER_EXT);
-#endif
- else
- shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
- if (!shader) {
- qWarning("Could not create shader of type %d.", int(shaderType));
- return false;
- }
- shaderGuard = createSharedResourceGuard(context, shader, freeShaderFunc);
- return true;
- } else {
- return false;
- }
-}
-
-bool QGLShaderPrivate::compile(QGLShader *q)
-{
- GLuint shader = shaderGuard ? shaderGuard->id() : 0;
- if (!shader)
- return false;
- glfuncs->glCompileShader(shader);
- GLint value = 0;
- glfuncs->glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
- compiled = (value != 0);
- value = 0;
- glfuncs->glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
- if (!compiled && value > 1) {
- char *logbuf = new char [value];
- GLint len;
- glfuncs->glGetShaderInfoLog(shader, value, &len, logbuf);
- log = QString::fromLatin1(logbuf);
- QString name = q->objectName();
-
- const char *types[] = {
- "Fragment",
- "Vertex",
- "Geometry",
- ""
- };
-
- const char *type = types[3];
- if (shaderType == QGLShader::Fragment)
- type = types[0];
- else if (shaderType == QGLShader::Vertex)
- type = types[1];
- else if (shaderType == QGLShader::Geometry)
- type = types[2];
-
- if (name.isEmpty())
- qWarning("QGLShader::compile(%s): %s", type, qPrintable(log));
- else
- qWarning("QGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log));
-
- delete [] logbuf;
- }
- return compiled;
-}
-
-void QGLShaderPrivate::deleteShader()
-{
- if (shaderGuard) {
- shaderGuard->free();
- shaderGuard = 0;
- }
-}
-
-/*!
- Constructs a new QGLShader object of the specified \a type
- and attaches it to \a parent. If shader programs are not supported,
- QGLShaderProgram::hasOpenGLShaderPrograms() will return false.
-
- This constructor is normally followed by a call to compileSourceCode()
- or compileSourceFile().
-
- The shader will be associated with the current QGLContext.
-
- \sa compileSourceCode(), compileSourceFile()
-*/
-QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
- : QObject(*new QGLShaderPrivate(QGLContext::currentContext(), type), parent)
-{
- Q_D(QGLShader);
- d->create();
-}
-
-/*!
- Constructs a new QGLShader object of the specified \a type
- and attaches it to \a parent. If shader programs are not supported,
- then QGLShaderProgram::hasOpenGLShaderPrograms() will return false.
-
- This constructor is normally followed by a call to compileSourceCode()
- or compileSourceFile().
-
- The shader will be associated with \a context.
-
- \sa compileSourceCode(), compileSourceFile()
-*/
-QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
- : QObject(*new QGLShaderPrivate(context ? context : QGLContext::currentContext(), type), parent)
-{
- Q_D(QGLShader);
-#ifndef QT_NO_DEBUG
- if (context && !QGLContext::areSharing(context, QGLContext::currentContext())) {
- qWarning("QGLShader::QGLShader: \'context\' must be the current context or sharing with it.");
- return;
- }
-#endif
- d->create();
-}
-
-/*!
- Deletes this shader. If the shader has been attached to a
- QGLShaderProgram object, then the actual shader will stay around
- until the QGLShaderProgram is destroyed.
-*/
-QGLShader::~QGLShader()
-{
-}
-
-/*!
- Returns the type of this shader.
-*/
-QGLShader::ShaderType QGLShader::shaderType() const
-{
- Q_D(const QGLShader);
- return d->shaderType;
-}
-
-// The precision qualifiers are useful on OpenGL/ES systems,
-// but usually not present on desktop systems. Define the
-// keywords to empty strings on desktop systems.
-#if !defined(QT_OPENGL_ES) || defined(QT_OPENGL_FORCE_SHADER_DEFINES)
-#define QGL_DEFINE_QUALIFIERS 1
-static const char qualifierDefines[] =
- "#define lowp\n"
- "#define mediump\n"
- "#define highp\n";
-
-#else
-
-// The "highp" qualifier doesn't exist in fragment shaders
-// on all ES platforms. When it doesn't exist, use "mediump".
-#define QGL_REDEFINE_HIGHP 1
-static const char redefineHighp[] =
- "#ifndef GL_FRAGMENT_PRECISION_HIGH\n"
- "#define highp mediump\n"
- "#endif\n";
-#endif
-
-/*!
- Sets the \a source code for this shader and compiles it.
- Returns \c true if the source was successfully compiled, false otherwise.
-
- \sa compileSourceFile()
-*/
-bool QGLShader::compileSourceCode(const char *source)
-{
- Q_D(QGLShader);
- if (d->shaderGuard && d->shaderGuard->id()) {
- QVarLengthArray<const char *, 4> src;
- QVarLengthArray<GLint, 4> srclen;
- int headerLen = 0;
- while (source && source[headerLen] == '#') {
- // Skip #version and #extension directives at the start of
- // the shader code. We need to insert the qualifierDefines
- // and redefineHighp just after them.
- if (qstrncmp(source + headerLen, "#version", 8) != 0 &&
- qstrncmp(source + headerLen, "#extension", 10) != 0) {
- break;
- }
- while (source[headerLen] != '\0' && source[headerLen] != '\n')
- ++headerLen;
- if (source[headerLen] == '\n')
- ++headerLen;
- }
- if (headerLen > 0) {
- src.append(source);
- srclen.append(GLint(headerLen));
- }
-#ifdef QGL_DEFINE_QUALIFIERS
- if (!QOpenGLContext::currentContext()->isOpenGLES()) {
- src.append(qualifierDefines);
- srclen.append(GLint(sizeof(qualifierDefines) - 1));
- }
-#endif
-#ifdef QGL_REDEFINE_HIGHP
- if (d->shaderType == Fragment
- && QOpenGLContext::currentContext()->isOpenGLES()) {
- src.append(redefineHighp);
- srclen.append(GLint(sizeof(redefineHighp) - 1));
- }
-#endif
- src.append(source + headerLen);
- srclen.append(GLint(qstrlen(source + headerLen)));
- d->glfuncs->glShaderSource(d->shaderGuard->id(), src.size(), src.data(), srclen.data());
- return d->compile(this);
- } else {
- return false;
- }
-}
-
-/*!
- \overload
-
- Sets the \a source code for this shader and compiles it.
- Returns \c true if the source was successfully compiled, false otherwise.
-
- \sa compileSourceFile()
-*/
-bool QGLShader::compileSourceCode(const QByteArray& source)
-{
- return compileSourceCode(source.constData());
-}
-
-/*!
- \overload
-
- Sets the \a source code for this shader and compiles it.
- Returns \c true if the source was successfully compiled, false otherwise.
-
- \sa compileSourceFile()
-*/
-bool QGLShader::compileSourceCode(const QString& source)
-{
- return compileSourceCode(source.toLatin1().constData());
-}
-
-/*!
- Sets the source code for this shader to the contents of \a fileName
- and compiles it. Returns \c true if the file could be opened and the
- source compiled, false otherwise.
-
- \sa compileSourceCode()
-*/
-bool QGLShader::compileSourceFile(const QString& fileName)
-{
- QFile file(fileName);
- if (!file.open(QFile::ReadOnly)) {
- qWarning() << "QGLShader: Unable to open file" << fileName;
- return false;
- }
-
- QByteArray contents = file.readAll();
- return compileSourceCode(contents.constData());
-}
-
-/*!
- Returns the source code for this shader.
-
- \sa compileSourceCode()
-*/
-QByteArray QGLShader::sourceCode() const
-{
- Q_D(const QGLShader);
- GLuint shader = d->shaderGuard ? d->shaderGuard->id() : 0;
- if (!shader)
- return QByteArray();
- GLint size = 0;
- d->glfuncs->glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &size);
- if (size <= 0)
- return QByteArray();
- GLint len = 0;
- char *source = new char [size];
- d->glfuncs->glGetShaderSource(shader, size, &len, source);
- QByteArray src(source);
- delete [] source;
- return src;
-}
-
-/*!
- Returns \c true if this shader has been compiled; false otherwise.
-
- \sa compileSourceCode(), compileSourceFile()
-*/
-bool QGLShader::isCompiled() const
-{
- Q_D(const QGLShader);
- return d->compiled;
-}
-
-/*!
- Returns the errors and warnings that occurred during the last compile.
-
- \sa compileSourceCode(), compileSourceFile()
-*/
-QString QGLShader::log() const
-{
- Q_D(const QGLShader);
- return d->log;
-}
-
-/*!
- Returns the OpenGL identifier associated with this shader.
-
- \sa QGLShaderProgram::programId()
-*/
-GLuint QGLShader::shaderId() const
-{
- Q_D(const QGLShader);
- return d->shaderGuard ? d->shaderGuard->id() : 0;
-}
-
-#undef ctx
-
-class ShaderProgramOpenGLFunctions : public QOpenGLFunctions
-{
-public:
- ShaderProgramOpenGLFunctions()
- : QOpenGLFunctions()
- , glProgramParameteri(0)
- {
- }
-
- typedef void (QOPENGLF_APIENTRYP type_glProgramParameteri)(GLuint program, GLenum pname, GLint value);
-
- void initializeGeometryShaderFunctions()
- {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- if (!context->isOpenGLES()) {
- glProgramParameteri = (type_glProgramParameteri)
- context->getProcAddress("glProgramParameteri");
-
- if (!glProgramParameteri) {
- glProgramParameteri = (type_glProgramParameteri)
- context->getProcAddress("glProgramParameteriEXT");
- }
- }
- }
-
- type_glProgramParameteri glProgramParameteri;
-};
-
-class QGLShaderProgramPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QGLShaderProgram)
-public:
- QGLShaderProgramPrivate(const QGLContext *)
- : programGuard(0)
- , linked(false)
- , inited(false)
- , removingShaders(false)
- , geometryVertexCount(64)
- , geometryInputType(0)
- , geometryOutputType(0)
- , glfuncs(new ShaderProgramOpenGLFunctions)
- {
- }
- ~QGLShaderProgramPrivate();
-
- QGLSharedResourceGuardBase *programGuard;
- bool linked;
- bool inited;
- bool removingShaders;
-
- int geometryVertexCount;
- GLenum geometryInputType;
- GLenum geometryOutputType;
-
- QString log;
- QList<QGLShader *> shaders;
- QList<QGLShader *> anonShaders;
-
- ShaderProgramOpenGLFunctions *glfuncs;
-
- bool hasShader(QGLShader::ShaderType type) const;
-};
-
-namespace {
- void freeProgramFunc(QGLContext *ctx, GLuint id)
- {
- Q_ASSERT(ctx);
- ctx->contextHandle()->functions()->glDeleteProgram(id);
- }
-}
-
-
-QGLShaderProgramPrivate::~QGLShaderProgramPrivate()
-{
- delete glfuncs;
- if (programGuard)
- programGuard->free();
-}
-
-bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const
-{
- for (QGLShader *shader : shaders) {
- if (shader->shaderType() == type)
- return true;
- }
- return false;
-}
-
-#define ctx QGLContext::currentContext()
-
-/*!
- Constructs a new shader program and attaches it to \a parent.
- The program will be invalid until addShader() is called.
-
- The shader program will be associated with the current QGLContext.
-
- \sa addShader()
-*/
-QGLShaderProgram::QGLShaderProgram(QObject *parent)
- : QObject(*new QGLShaderProgramPrivate(QGLContext::currentContext()), parent)
-{
-}
-
-/*!
- Constructs a new shader program and attaches it to \a parent.
- The program will be invalid until addShader() is called.
-
- The shader program will be associated with \a context.
-
- \sa addShader()
-*/
-QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
- : QObject(*new QGLShaderProgramPrivate(context), parent)
-{
-}
-
-/*!
- Deletes this shader program.
-*/
-QGLShaderProgram::~QGLShaderProgram()
-{
-}
-
-bool QGLShaderProgram::init()
-{
- Q_D(QGLShaderProgram);
- if ((d->programGuard && d->programGuard->id()) || d->inited)
- return true;
- d->inited = true;
- QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext());
- if (!context)
- return false;
- d->glfuncs->initializeOpenGLFunctions();
- d->glfuncs->initializeGeometryShaderFunctions();
- if (d->glfuncs->hasOpenGLFeature(QOpenGLFunctions::Shaders)) {
- GLuint program = d->glfuncs->glCreateProgram();
- if (!program) {
- qWarning("QGLShaderProgram: could not create shader program");
- return false;
- }
- if (d->programGuard)
- delete d->programGuard;
- d->programGuard = createSharedResourceGuard(context, program, freeProgramFunc);
- return true;
- } else {
- qWarning("QGLShaderProgram: shader programs are not supported");
- return false;
- }
-}
-
-/*!
- Adds a compiled \a shader to this shader program. Returns \c true
- if the shader could be added, or false otherwise.
-
- Ownership of the \a shader object remains with the caller.
- It will not be deleted when this QGLShaderProgram instance
- is deleted. This allows the caller to add the same shader
- to multiple shader programs.
-
- \sa addShaderFromSourceCode(), addShaderFromSourceFile()
- \sa removeShader(), link(), removeAllShaders()
-*/
-bool QGLShaderProgram::addShader(QGLShader *shader)
-{
- Q_D(QGLShaderProgram);
- if (!init())
- return false;
- if (d->shaders.contains(shader))
- return true; // Already added to this shader program.
- if (d->programGuard && d->programGuard->id() && shader) {
- if (!shader->d_func()->shaderGuard || !shader->d_func()->shaderGuard->id())
- return false;
- if (d->programGuard->group() != shader->d_func()->shaderGuard->group()) {
- qWarning("QGLShaderProgram::addShader: Program and shader are not associated with same context.");
- return false;
- }
- d->glfuncs->glAttachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
- d->linked = false; // Program needs to be relinked.
- d->shaders.append(shader);
- connect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
- return true;
- } else {
- return false;
- }
-}
-
-/*!
- Compiles \a source as a shader of the specified \a type and
- adds it to this shader program. Returns \c true if compilation
- was successful, false otherwise. The compilation errors
- and warnings will be made available via log().
-
- This function is intended to be a short-cut for quickly
- adding vertex and fragment shaders to a shader program without
- creating an instance of QGLShader first.
-
- \sa addShader(), addShaderFromSourceFile()
- \sa removeShader(), link(), log(), removeAllShaders()
-*/
-bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const char *source)
-{
- Q_D(QGLShaderProgram);
- if (!init())
- return false;
- QGLShader *shader = new QGLShader(type, this);
- if (!shader->compileSourceCode(source)) {
- d->log = shader->log();
- delete shader;
- return false;
- }
- d->anonShaders.append(shader);
- return addShader(shader);
-}
-
-/*!
- \overload
-
- Compiles \a source as a shader of the specified \a type and
- adds it to this shader program. Returns \c true if compilation
- was successful, false otherwise. The compilation errors
- and warnings will be made available via log().
-
- This function is intended to be a short-cut for quickly
- adding vertex and fragment shaders to a shader program without
- creating an instance of QGLShader first.
-
- \sa addShader(), addShaderFromSourceFile()
- \sa removeShader(), link(), log(), removeAllShaders()
-*/
-bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const QByteArray& source)
-{
- return addShaderFromSourceCode(type, source.constData());
-}
-
-/*!
- \overload
-
- Compiles \a source as a shader of the specified \a type and
- adds it to this shader program. Returns \c true if compilation
- was successful, false otherwise. The compilation errors
- and warnings will be made available via log().
-
- This function is intended to be a short-cut for quickly
- adding vertex and fragment shaders to a shader program without
- creating an instance of QGLShader first.
-
- \sa addShader(), addShaderFromSourceFile()
- \sa removeShader(), link(), log(), removeAllShaders()
-*/
-bool QGLShaderProgram::addShaderFromSourceCode(QGLShader::ShaderType type, const QString& source)
-{
- return addShaderFromSourceCode(type, source.toLatin1().constData());
-}
-
-/*!
- Compiles the contents of \a fileName as a shader of the specified
- \a type and adds it to this shader program. Returns \c true if
- compilation was successful, false otherwise. The compilation errors
- and warnings will be made available via log().
-
- This function is intended to be a short-cut for quickly
- adding vertex and fragment shaders to a shader program without
- creating an instance of QGLShader first.
-
- \sa addShader(), addShaderFromSourceCode()
-*/
-bool QGLShaderProgram::addShaderFromSourceFile
- (QGLShader::ShaderType type, const QString& fileName)
-{
- Q_D(QGLShaderProgram);
- if (!init())
- return false;
- QGLShader *shader = new QGLShader(type, this);
- if (!shader->compileSourceFile(fileName)) {
- d->log = shader->log();
- delete shader;
- return false;
- }
- d->anonShaders.append(shader);
- return addShader(shader);
-}
-
-/*!
- Removes \a shader from this shader program. The object is not deleted.
-
- The shader program must be valid in the current QGLContext.
-
- \sa addShader(), link(), removeAllShaders()
-*/
-void QGLShaderProgram::removeShader(QGLShader *shader)
-{
- Q_D(QGLShaderProgram);
- if (d->programGuard && d->programGuard->id()
- && shader && shader->d_func()->shaderGuard)
- {
- d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
- }
- d->linked = false; // Program needs to be relinked.
- if (shader) {
- d->shaders.removeAll(shader);
- d->anonShaders.removeAll(shader);
- disconnect(shader, SIGNAL(destroyed()), this, SLOT(shaderDestroyed()));
- }
-}
-
-/*!
- Returns a list of all shaders that have been added to this shader
- program using addShader().
-
- \sa addShader(), removeShader()
-*/
-QList<QGLShader *> QGLShaderProgram::shaders() const
-{
- Q_D(const QGLShaderProgram);
- return d->shaders;
-}
-
-/*!
- Removes all of the shaders that were added to this program previously.
- The QGLShader objects for the shaders will not be deleted if they
- were constructed externally. QGLShader objects that are constructed
- internally by QGLShaderProgram will be deleted.
-
- \sa addShader(), removeShader()
-*/
-void QGLShaderProgram::removeAllShaders()
-{
- Q_D(QGLShaderProgram);
- d->removingShaders = true;
- if (d->programGuard) {
- if (const auto programGuardId = d->programGuard->id()) {
- for (QGLShader *shader : qAsConst(d->shaders)) {
- if (shader && shader->d_func()->shaderGuard)
- d->glfuncs->glDetachShader(programGuardId, shader->d_func()->shaderGuard->id());
- }
- }
- }
- // Delete shader objects that were created anonymously.
- qDeleteAll(d->anonShaders);
- d->shaders.clear();
- d->anonShaders.clear();
- d->linked = false; // Program needs to be relinked.
- d->removingShaders = false;
-}
-
-/*!
- Links together the shaders that were added to this program with
- addShader(). Returns \c true if the link was successful or
- false otherwise. If the link failed, the error messages can
- be retrieved with log().
-
- Subclasses can override this function to initialize attributes
- and uniform variables for use in specific shader programs.
-
- If the shader program was already linked, calling this
- function again will force it to be re-linked.
-
- \sa addShader(), log()
-*/
-bool QGLShaderProgram::link()
-{
- Q_D(QGLShaderProgram);
- GLuint program = d->programGuard ? d->programGuard->id() : 0;
- if (!program)
- return false;
-
- GLint value;
- if (d->shaders.isEmpty()) {
- // If there are no explicit shaders, then it is possible that the
- // application added a program binary with glProgramBinaryOES(),
- // or otherwise populated the shaders itself. Check to see if the
- // program is already linked and bail out if so.
- value = 0;
- d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
- d->linked = (value != 0);
- if (d->linked)
- return true;
- }
-
-#if !defined(QT_OPENGL_ES_2)
- // Set up the geometry shader parameters
- if (!QOpenGLContext::currentContext()->isOpenGLES()
- && d->glfuncs->glProgramParameteri) {
- for (QGLShader *shader : qAsConst(d->shaders)) {
- if (shader->shaderType() & QGLShader::Geometry) {
- d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_INPUT_TYPE_EXT,
- d->geometryInputType);
- d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
- d->geometryOutputType);
- d->glfuncs->glProgramParameteri(program, GL_GEOMETRY_VERTICES_OUT_EXT,
- d->geometryVertexCount);
- break;
- }
- }
- }
-#endif
-
- d->glfuncs->glLinkProgram(program);
- value = 0;
- d->glfuncs->glGetProgramiv(program, GL_LINK_STATUS, &value);
- d->linked = (value != 0);
- value = 0;
- d->glfuncs->glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
- d->log = QString();
- if (value > 1) {
- char *logbuf = new char [value];
- GLint len;
- d->glfuncs->glGetProgramInfoLog(program, value, &len, logbuf);
- d->log = QString::fromLatin1(logbuf);
- QString name = objectName();
- if (!d->linked) {
- if (name.isEmpty())
- qWarning() << "QGLShader::link:" << d->log;
- else
- qWarning() << "QGLShader::link[" << name << "]:" << d->log;
- }
- delete [] logbuf;
- }
- return d->linked;
-}
-
-/*!
- Returns \c true if this shader program has been linked; false otherwise.
-
- \sa link()
-*/
-bool QGLShaderProgram::isLinked() const
-{
- Q_D(const QGLShaderProgram);
- return d->linked;
-}
-
-/*!
- Returns the errors and warnings that occurred during the last link()
- or addShader() with explicitly specified source code.
-
- \sa link()
-*/
-QString QGLShaderProgram::log() const
-{
- Q_D(const QGLShaderProgram);
- return d->log;
-}
-
-/*!
- Binds this shader program to the active QGLContext and makes
- it the current shader program. Any previously bound shader program
- is released. This is equivalent to calling \c{glUseProgram()} on
- programId(). Returns \c true if the program was successfully bound;
- false otherwise. If the shader program has not yet been linked,
- or it needs to be re-linked, this function will call link().
-
- \sa link(), release()
-*/
-bool QGLShaderProgram::bind()
-{
- Q_D(QGLShaderProgram);
- GLuint program = d->programGuard ? d->programGuard->id() : 0;
- if (!program)
- return false;
- if (!d->linked && !link())
- return false;
-#ifndef QT_NO_DEBUG
- if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup()) {
- qWarning("QGLShaderProgram::bind: program is not valid in the current context.");
- return false;
- }
-#endif
- d->glfuncs->glUseProgram(program);
- return true;
-}
-
-#undef ctx
-#define ctx QGLContext::currentContext()
-
-/*!
- Releases the active shader program from the current QGLContext.
- This is equivalent to calling \c{glUseProgram(0)}.
-
- \sa bind()
-*/
-void QGLShaderProgram::release()
-{
- Q_D(QGLShaderProgram);
-#ifndef QT_NO_DEBUG
- if (d->programGuard && d->programGuard->group() != QOpenGLContextGroup::currentContextGroup())
- qWarning("QGLShaderProgram::release: program is not valid in the current context.");
-#endif
- d->glfuncs->glUseProgram(0);
-}
-
-/*!
- Returns the OpenGL identifier associated with this shader program.
-
- \sa QGLShader::shaderId()
-*/
-GLuint QGLShaderProgram::programId() const
-{
- Q_D(const QGLShaderProgram);
- GLuint id = d->programGuard ? d->programGuard->id() : 0;
- if (id)
- return id;
-
- // Create the identifier if we don't have one yet. This is for
- // applications that want to create the attached shader configuration
- // themselves, particularly those using program binaries.
- if (!const_cast<QGLShaderProgram *>(this)->init())
- return 0;
- return d->programGuard ? d->programGuard->id() : 0;
-}
-
-/*!
- Binds the attribute \a name to the specified \a location. This
- function can be called before or after the program has been linked.
- Any attributes that have not been explicitly bound when the program
- is linked will be assigned locations automatically.
-
- When this function is called after the program has been linked,
- the program will need to be relinked for the change to take effect.
-
- \sa attributeLocation()
-*/
-void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
-{
- Q_D(QGLShaderProgram);
- if (!init() || !d->programGuard || !d->programGuard->id())
- return;
- d->glfuncs->glBindAttribLocation(d->programGuard->id(), location, name);
- d->linked = false; // Program needs to be relinked.
-}
-
-/*!
- \overload
-
- Binds the attribute \a name to the specified \a location. This
- function can be called before or after the program has been linked.
- Any attributes that have not been explicitly bound when the program
- is linked will be assigned locations automatically.
-
- When this function is called after the program has been linked,
- the program will need to be relinked for the change to take effect.
-
- \sa attributeLocation()
-*/
-void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
-{
- bindAttributeLocation(name.constData(), location);
-}
-
-/*!
- \overload
-
- Binds the attribute \a name to the specified \a location. This
- function can be called before or after the program has been linked.
- Any attributes that have not been explicitly bound when the program
- is linked will be assigned locations automatically.
-
- When this function is called after the program has been linked,
- the program will need to be relinked for the change to take effect.
-
- \sa attributeLocation()
-*/
-void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
-{
- bindAttributeLocation(name.toLatin1().constData(), location);
-}
-
-/*!
- Returns the location of the attribute \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- attribute for this shader program.
-
- \sa uniformLocation(), bindAttributeLocation()
-*/
-int QGLShaderProgram::attributeLocation(const char *name) const
-{
- Q_D(const QGLShaderProgram);
- if (d->linked && d->programGuard && d->programGuard->id()) {
- return d->glfuncs->glGetAttribLocation(d->programGuard->id(), name);
- } else {
- qWarning() << "QGLShaderProgram::attributeLocation(" << name
- << "): shader program is not linked";
- return -1;
- }
-}
-
-/*!
- \overload
-
- Returns the location of the attribute \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- attribute for this shader program.
-
- \sa uniformLocation(), bindAttributeLocation()
-*/
-int QGLShaderProgram::attributeLocation(const QByteArray& name) const
-{
- return attributeLocation(name.constData());
-}
-
-/*!
- \overload
-
- Returns the location of the attribute \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- attribute for this shader program.
-
- \sa uniformLocation(), bindAttributeLocation()
-*/
-int QGLShaderProgram::attributeLocation(const QString& name) const
-{
- return attributeLocation(name.toLatin1().constData());
-}
-
-/*!
- Sets the attribute at \a location in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glVertexAttrib1fv(location, &value);
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
-{
- setAttributeValue(attributeLocation(name), value);
-}
-
-/*!
- Sets the attribute at \a location in the current context to
- the 2D vector (\a x, \a y).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[2] = {x, y};
- d->glfuncs->glVertexAttrib2fv(location, values);
- }
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to
- the 2D vector (\a x, \a y).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
-{
- setAttributeValue(attributeLocation(name), x, y);
-}
-
-/*!
- Sets the attribute at \a location in the current context to
- the 3D vector (\a x, \a y, \a z).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (int location, GLfloat x, GLfloat y, GLfloat z)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[3] = {x, y, z};
- d->glfuncs->glVertexAttrib3fv(location, values);
- }
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to
- the 3D vector (\a x, \a y, \a z).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (const char *name, GLfloat x, GLfloat y, GLfloat z)
-{
- setAttributeValue(attributeLocation(name), x, y, z);
-}
-
-/*!
- Sets the attribute at \a location in the current context to
- the 4D vector (\a x, \a y, \a z, \a w).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {x, y, z, w};
- d->glfuncs->glVertexAttrib4fv(location, values);
- }
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to
- the 4D vector (\a x, \a y, \a z, \a w).
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- setAttributeValue(attributeLocation(name), x, y, z, w);
-}
-
-/*!
- Sets the attribute at \a location in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
-{
- setAttributeValue(attributeLocation(name), value);
-}
-
-/*!
- Sets the attribute at \a location in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
-{
- setAttributeValue(attributeLocation(name), value);
-}
-
-/*!
- Sets the attribute at \a location in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
-{
- setAttributeValue(attributeLocation(name), value);
-}
-
-/*!
- Sets the attribute at \a location in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(value.redF()), GLfloat(value.greenF()),
- GLfloat(value.blueF()), GLfloat(value.alphaF())};
- d->glfuncs->glVertexAttrib4fv(location, values);
- }
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to \a value.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
-{
- setAttributeValue(attributeLocation(name), value);
-}
-
-/*!
- Sets the attribute at \a location in the current context to the
- contents of \a values, which contains \a columns elements, each
- consisting of \a rows elements. The \a rows value should be
- 1, 2, 3, or 4. This function is typically used to set matrix
- values and column vectors.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (int location, const GLfloat *values, int columns, int rows)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (rows < 1 || rows > 4) {
- qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
- return;
- }
- if (location != -1) {
- while (columns-- > 0) {
- if (rows == 1)
- d->glfuncs->glVertexAttrib1fv(location, values);
- else if (rows == 2)
- d->glfuncs->glVertexAttrib2fv(location, values);
- else if (rows == 3)
- d->glfuncs->glVertexAttrib3fv(location, values);
- else
- d->glfuncs->glVertexAttrib4fv(location, values);
- values += rows;
- ++location;
- }
- }
-}
-
-/*!
- \overload
-
- Sets the attribute called \a name in the current context to the
- contents of \a values, which contains \a columns elements, each
- consisting of \a rows elements. The \a rows value should be
- 1, 2, 3, or 4. This function is typically used to set matrix
- values and column vectors.
-
- \sa setUniformValue()
-*/
-void QGLShaderProgram::setAttributeValue
- (const char *name, const GLfloat *values, int columns, int rows)
-{
- setAttributeValue(attributeLocation(name), values, columns, rows);
-}
-
-/*!
- Sets an array of vertex \a values on the attribute at \a location
- in this shader program. The \a tupleSize indicates the number of
- components per vertex (1, 2, 3, or 4), and the \a stride indicates
- the number of bytes between vertices. A default \a stride value
- of zero indicates that the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (int location, const GLfloat *values, int tupleSize, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, tupleSize, GL_FLOAT, GL_FALSE,
- stride, values);
- }
-}
-
-/*!
- Sets an array of 2D vertex \a values on the attribute at \a location
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (int location, const QVector2D *values, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
- stride, values);
- }
-}
-
-/*!
- Sets an array of 3D vertex \a values on the attribute at \a location
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (int location, const QVector3D *values, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
- stride, values);
- }
-}
-
-/*!
- Sets an array of 4D vertex \a values on the attribute at \a location
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (int location, const QVector4D *values, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
- stride, values);
- }
-}
-
-/*!
- Sets an array of vertex \a values on the attribute at \a location
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The \a type indicates the type of elements in the \a values array,
- usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
- indicates the number of components per vertex: 1, 2, 3, or 4.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- The setAttributeBuffer() function can be used to set the attribute
- array to an offset within a vertex buffer.
-
- \note Normalization will be enabled. If this is not desired, call
- glVertexAttribPointer directly through QGLFunctions.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray(), setAttributeBuffer()
- \since 4.7
-*/
-void QGLShaderProgram::setAttributeArray
- (int location, GLenum type, const void *values, int tupleSize, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE,
- stride, values);
- }
-}
-
-/*!
- \overload
-
- Sets an array of vertex \a values on the attribute called \a name
- in this shader program. The \a tupleSize indicates the number of
- components per vertex (1, 2, 3, or 4), and the \a stride indicates
- the number of bytes between vertices. A default \a stride value
- of zero indicates that the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on \a name. Otherwise the value specified with setAttributeValue()
- for \a name will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (const char *name, const GLfloat *values, int tupleSize, int stride)
-{
- setAttributeArray(attributeLocation(name), values, tupleSize, stride);
-}
-
-/*!
- \overload
-
- Sets an array of 2D vertex \a values on the attribute called \a name
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on \a name. Otherwise the value specified with setAttributeValue()
- for \a name will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (const char *name, const QVector2D *values, int stride)
-{
- setAttributeArray(attributeLocation(name), values, stride);
-}
-
-/*!
- \overload
-
- Sets an array of 3D vertex \a values on the attribute called \a name
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on \a name. Otherwise the value specified with setAttributeValue()
- for \a name will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (const char *name, const QVector3D *values, int stride)
-{
- setAttributeArray(attributeLocation(name), values, stride);
-}
-
-/*!
- \overload
-
- Sets an array of 4D vertex \a values on the attribute called \a name
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The array will become active when enableAttributeArray() is called
- on \a name. Otherwise the value specified with setAttributeValue()
- for \a name will be used.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray()
-*/
-void QGLShaderProgram::setAttributeArray
- (const char *name, const QVector4D *values, int stride)
-{
- setAttributeArray(attributeLocation(name), values, stride);
-}
-
-/*!
- \overload
-
- Sets an array of vertex \a values on the attribute called \a name
- in this shader program. The \a stride indicates the number of bytes
- between vertices. A default \a stride value of zero indicates that
- the vertices are densely packed in \a values.
-
- The \a type indicates the type of elements in the \a values array,
- usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a tupleSize
- indicates the number of components per vertex: 1, 2, 3, or 4.
-
- The array will become active when enableAttributeArray() is called
- on the \a name. Otherwise the value specified with
- setAttributeValue() for \a name will be used.
-
- The setAttributeBuffer() function can be used to set the attribute
- array to an offset within a vertex buffer.
-
- \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
- \sa disableAttributeArray(), setAttributeBuffer()
- \since 4.7
-*/
-void QGLShaderProgram::setAttributeArray
- (const char *name, GLenum type, const void *values, int tupleSize, int stride)
-{
- setAttributeArray(attributeLocation(name), type, values, tupleSize, stride);
-}
-
-/*!
- Sets an array of vertex values on the attribute at \a location in
- this shader program, starting at a specific \a offset in the
- currently bound vertex buffer. The \a stride indicates the number
- of bytes between vertices. A default \a stride value of zero
- indicates that the vertices are densely packed in the value array.
-
- The \a type indicates the type of elements in the vertex value
- array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
- tupleSize indicates the number of components per vertex: 1, 2, 3,
- or 4.
-
- The array will become active when enableAttributeArray() is called
- on the \a location. Otherwise the value specified with
- setAttributeValue() for \a location will be used.
-
- \note Normalization will be enabled. If this is not desired, call
- glVertexAttribPointer directly though QGLFunctions.
-
- \sa setAttributeArray()
- \since 4.7
-*/
-void QGLShaderProgram::setAttributeBuffer
- (int location, GLenum type, int offset, int tupleSize, int stride)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride,
- reinterpret_cast<const void *>(qintptr(offset)));
- }
-}
-
-/*!
- \overload
-
- Sets an array of vertex values on the attribute called \a name
- in this shader program, starting at a specific \a offset in the
- currently bound vertex buffer. The \a stride indicates the number
- of bytes between vertices. A default \a stride value of zero
- indicates that the vertices are densely packed in the value array.
-
- The \a type indicates the type of elements in the vertex value
- array, usually \c{GL_FLOAT}, \c{GL_UNSIGNED_BYTE}, etc. The \a
- tupleSize indicates the number of components per vertex: 1, 2, 3,
- or 4.
-
- The array will become active when enableAttributeArray() is called
- on the \a name. Otherwise the value specified with
- setAttributeValue() for \a name will be used.
-
- \sa setAttributeArray()
- \since 4.7
-*/
-void QGLShaderProgram::setAttributeBuffer
- (const char *name, GLenum type, int offset, int tupleSize, int stride)
-{
- setAttributeBuffer(attributeLocation(name), type, offset, tupleSize, stride);
-}
-
-/*!
- Enables the vertex array at \a location in this shader program
- so that the value set by setAttributeArray() on \a location
- will be used by the shader program.
-
- \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
- \sa setUniformValue()
-*/
-void QGLShaderProgram::enableAttributeArray(int location)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glEnableVertexAttribArray(location);
-}
-
-/*!
- \overload
-
- Enables the vertex array called \a name in this shader program
- so that the value set by setAttributeArray() on \a name
- will be used by the shader program.
-
- \sa disableAttributeArray(), setAttributeArray(), setAttributeValue()
- \sa setUniformValue()
-*/
-void QGLShaderProgram::enableAttributeArray(const char *name)
-{
- enableAttributeArray(attributeLocation(name));
-}
-
-/*!
- Disables the vertex array at \a location in this shader program
- that was enabled by a previous call to enableAttributeArray().
-
- \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
- \sa setUniformValue()
-*/
-void QGLShaderProgram::disableAttributeArray(int location)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glDisableVertexAttribArray(location);
-}
-
-/*!
- \overload
-
- Disables the vertex array called \a name in this shader program
- that was enabled by a previous call to enableAttributeArray().
-
- \sa enableAttributeArray(), setAttributeArray(), setAttributeValue()
- \sa setUniformValue()
-*/
-void QGLShaderProgram::disableAttributeArray(const char *name)
-{
- disableAttributeArray(attributeLocation(name));
-}
-
-/*!
- Returns the location of the uniform variable \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- uniform variable for this shader program.
-
- \sa attributeLocation()
-*/
-int QGLShaderProgram::uniformLocation(const char *name) const
-{
- Q_D(const QGLShaderProgram);
- Q_UNUSED(d);
- if (d->linked && d->programGuard && d->programGuard->id()) {
- return d->glfuncs->glGetUniformLocation(d->programGuard->id(), name);
- } else {
- qWarning() << "QGLShaderProgram::uniformLocation(" << name
- << "): shader program is not linked";
- return -1;
- }
-}
-
-/*!
- \overload
-
- Returns the location of the uniform variable \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- uniform variable for this shader program.
-
- \sa attributeLocation()
-*/
-int QGLShaderProgram::uniformLocation(const QByteArray& name) const
-{
- return uniformLocation(name.constData());
-}
-
-/*!
- \overload
-
- Returns the location of the uniform variable \a name within this shader
- program's parameter list. Returns -1 if \a name is not a valid
- uniform variable for this shader program.
-
- \sa attributeLocation()
-*/
-int QGLShaderProgram::uniformLocation(const QString& name) const
-{
- return uniformLocation(name.toLatin1().constData());
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, GLfloat value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform1fv(location, 1, &value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, GLint value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform1i(location, value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, GLint value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
- This function should be used when setting sampler values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, GLuint value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform1i(location, value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value. This function should be used when setting sampler values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, GLuint value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the 2D vector (\a x, \a y).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[2] = {x, y};
- d->glfuncs->glUniform2fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context to
- the 2D vector (\a x, \a y).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
-{
- setUniformValue(uniformLocation(name), x, y);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the 3D vector (\a x, \a y, \a z).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue
- (int location, GLfloat x, GLfloat y, GLfloat z)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[3] = {x, y, z};
- d->glfuncs->glUniform3fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context to
- the 3D vector (\a x, \a y, \a z).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue
- (const char *name, GLfloat x, GLfloat y, GLfloat z)
-{
- setUniformValue(uniformLocation(name), x, y, z);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the 4D vector (\a x, \a y, \a z, \a w).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue
- (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {x, y, z, w};
- d->glfuncs->glUniform4fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context to
- the 4D vector (\a x, \a y, \a z, \a w).
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue
- (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
-{
- setUniformValue(uniformLocation(name), x, y, z, w);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the red, green, blue, and alpha components of \a color.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QColor& color)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(color.redF()), GLfloat(color.greenF()),
- GLfloat(color.blueF()), GLfloat(color.alphaF())};
- d->glfuncs->glUniform4fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context to
- the red, green, blue, and alpha components of \a color.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
-{
- setUniformValue(uniformLocation(name), color);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the x and y coordinates of \a point.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QPoint& point)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
- d->glfuncs->glUniform2fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable associated with \a name in the current
- context to the x and y coordinates of \a point.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
-{
- setUniformValue(uniformLocation(name), point);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the x and y coordinates of \a point.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QPointF& point)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(point.x()), GLfloat(point.y())};
- d->glfuncs->glUniform2fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable associated with \a name in the current
- context to the x and y coordinates of \a point.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
-{
- setUniformValue(uniformLocation(name), point);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the width and height of the given \a size.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QSize& size)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
- d->glfuncs->glUniform2fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable associated with \a name in the current
- context to the width and height of the given \a size.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QSize& size)
-{
- setUniformValue(uniformLocation(name), size);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to
- the width and height of the given \a size.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QSizeF& size)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1) {
- GLfloat values[4] = {GLfloat(size.width()), GLfloat(size.height())};
- d->glfuncs->glUniform2fv(location, 1, values);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable associated with \a name in the current
- context to the width and height of the given \a size.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
-{
- setUniformValue(uniformLocation(name), size);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 2x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 2x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 2x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform3fv(location, 2, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 2x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 2x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform4fv(location, 2, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 2x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 3x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform2fv(location, 3, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 3x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 3x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 3x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 3x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform4fv(location, 3, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 3x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 4x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform2fv(location, 4, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 4x2 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 4x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniform3fv(location, 4, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 4x3 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context
- to a 4x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
-{
- Q_D(QGLShaderProgram);
- d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value.constData());
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 4x4 matrix \a value.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable at \a location in the current context
- to a 2x2 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
- \since 4.7
-*/
-void QGLShaderProgram::setUniformValue(int location, const GLfloat value[2][2])
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniformMatrix2fv(location, 1, GL_FALSE, value[0]);
-}
-
-/*!
- \overload
-
- Sets the uniform variable at \a location in the current context
- to a 3x3 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
- \since 4.7
-*/
-void QGLShaderProgram::setUniformValue(int location, const GLfloat value[3][3])
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, value[0]);
-}
-
-/*!
- \overload
-
- Sets the uniform variable at \a location in the current context
- to a 4x4 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
-}
-
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 2x2 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
- \since 4.7
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[2][2])
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 3x3 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
- \since 4.7
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[3][3])
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context
- to a 4x4 matrix \a value. The matrix elements must be specified
- in column-major order.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable at \a location in the current context to a
- 3x3 transformation matrix \a value that is specified as a QTransform value.
-
- To set a QTransform value as a 4x4 matrix in a shader, use
- \c{setUniformValue(location, QMatrix4x4(value))}.
-*/
-void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
-{
- Q_D(QGLShaderProgram);
- if (location != -1) {
- GLfloat mat[3][3] = {
- {GLfloat(value.m11()), GLfloat(value.m12()), GLfloat(value.m13())},
- {GLfloat(value.m21()), GLfloat(value.m22()), GLfloat(value.m23())},
- {GLfloat(value.m31()), GLfloat(value.m32()), GLfloat(value.m33())}
- };
- d->glfuncs->glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable called \a name in the current context to a
- 3x3 transformation matrix \a value that is specified as a QTransform value.
-
- To set a QTransform value as a 4x4 matrix in a shader, use
- \c{setUniformValue(name, QMatrix4x4(value))}.
-*/
-void QGLShaderProgram::setUniformValue
- (const char *name, const QTransform& value)
-{
- setUniformValue(uniformLocation(name), value);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniform1iv(location, count, values);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray
- (const char *name, const GLint *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count elements of \a values. This overload
- should be used when setting an array of sampler values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count)
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniform1iv(location, count, reinterpret_cast<const GLint *>(values));
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count elements of \a values. This overload
- should be used when setting an array of sampler values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray
- (const char *name, const GLuint *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count elements of \a values. Each element
- has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize)
-{
- Q_D(QGLShaderProgram);
- if (location != -1) {
- if (tupleSize == 1)
- d->glfuncs->glUniform1fv(location, count, values);
- else if (tupleSize == 2)
- d->glfuncs->glUniform2fv(location, count, values);
- else if (tupleSize == 3)
- d->glfuncs->glUniform3fv(location, count, values);
- else if (tupleSize == 4)
- d->glfuncs->glUniform4fv(location, count, values);
- else
- qWarning() << "QGLShaderProgram::setUniformValue: size" << tupleSize << "not supported";
- }
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count elements of \a values. Each element
- has \a tupleSize components. The \a tupleSize must be 1, 2, 3, or 4.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray
- (const char *name, const GLfloat *values, int count, int tupleSize)
-{
- setUniformValueArray(uniformLocation(name), values, count, tupleSize);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 2D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 2D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 3D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
-{
- Q_D(QGLShaderProgram);
- if (location != -1)
- d->glfuncs->glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 3D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 4D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- if (location != -1)
- d->glfuncs->glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 4D vector elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-// We have to repack matrix arrays from qreal to GLfloat.
-#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
- if (location == -1 || count <= 0) \
- return; \
- if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
- func(location, count, GL_FALSE, \
- reinterpret_cast<const GLfloat *>(values[0].constData())); \
- } else { \
- QVarLengthArray<GLfloat> temp(cols * rows * count); \
- for (int index = 0; index < count; ++index) { \
- for (int index2 = 0; index2 < (cols * rows); ++index2) { \
- temp.data()[cols * rows * index + index2] = \
- values[index].constData()[index2]; \
- } \
- } \
- func(location, count, GL_FALSE, temp.constData()); \
- }
-#define setUniformGenericMatrixArray(colfunc,location,values,count,type,cols,rows) \
- if (location == -1 || count <= 0) \
- return; \
- if (sizeof(type) == sizeof(GLfloat) * cols * rows) { \
- const GLfloat *data = reinterpret_cast<const GLfloat *> \
- (values[0].constData()); \
- colfunc(location, count * cols, data); \
- } else { \
- QVarLengthArray<GLfloat> temp(cols * rows * count); \
- for (int index = 0; index < count; ++index) { \
- for (int index2 = 0; index2 < (cols * rows); ++index2) { \
- temp.data()[cols * rows * index + index2] = \
- values[index].constData()[index2]; \
- } \
- } \
- colfunc(location, count * cols, temp.constData()); \
- }
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 2x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformMatrixArray
- (d->glfuncs->glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 2x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 2x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform3fv, location, values, count,
- QMatrix2x3, 2, 3);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 2x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 2x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform4fv, location, values, count,
- QMatrix2x4, 2, 4);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 2x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 3x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform2fv, location, values, count,
- QMatrix3x2, 3, 2);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 3x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 3x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformMatrixArray
- (d->glfuncs->glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 3x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 3x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform4fv, location, values, count,
- QMatrix3x4, 3, 4);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 3x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 4x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform2fv, location, values, count,
- QMatrix4x2, 4, 2);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 4x2 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 4x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformGenericMatrixArray
- (d->glfuncs->glUniform3fv, location, values, count,
- QMatrix4x3, 4, 3);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 4x3 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-/*!
- Sets the uniform variable array at \a location in the current
- context to the \a count 4x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
-{
- Q_D(QGLShaderProgram);
- Q_UNUSED(d);
- setUniformMatrixArray
- (d->glfuncs->glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
-}
-
-/*!
- \overload
-
- Sets the uniform variable array called \a name in the current
- context to the \a count 4x4 matrix elements of \a values.
-
- \sa setAttributeValue()
-*/
-void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
-{
- setUniformValueArray(uniformLocation(name), values, count);
-}
-
-#undef ctx
-
-/*!
- Returns the hardware limit for how many vertices a geometry shader
- can output.
-
- \since 4.7
-
- \sa setGeometryOutputVertexCount()
-*/
-int QGLShaderProgram::maxGeometryOutputVertices() const
-{
- GLint n = 0;
-#if !defined(QT_OPENGL_ES_2)
- Q_D(const QGLShaderProgram);
- if (!QOpenGLContext::currentContext()->isOpenGLES())
- d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
-#endif
- return n;
-}
-
-/*!
- Sets the maximum number of vertices the current geometry shader
- program will produce, if active, to \a count.
-
- \since 4.7
-
- This parameter takes effect the next time the program is linked.
-*/
-void QGLShaderProgram::setGeometryOutputVertexCount(int count)
-{
-#ifndef QT_NO_DEBUG
- int max = maxGeometryOutputVertices();
- if (count > max) {
- qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
- count, max);
- }
-#endif
- d_func()->geometryVertexCount = count;
-}
-
-
-/*!
- Returns the maximum number of vertices the current geometry shader
- program will produce, if active.
-
- \since 4.7
-
- This parameter takes effect the ntext time the program is linked.
-*/
-int QGLShaderProgram::geometryOutputVertexCount() const
-{
- return d_func()->geometryVertexCount;
-}
-
-
-/*!
- Sets the input type from \a inputType.
-
- This parameter takes effect the next time the program is linked.
-*/
-void QGLShaderProgram::setGeometryInputType(GLenum inputType)
-{
- d_func()->geometryInputType = inputType;
-}
-
-
-/*!
- Returns the geometry shader input type, if active.
-
- This parameter takes effect the next time the program is linked.
-
- \since 4.7
- */
-
-GLenum QGLShaderProgram::geometryInputType() const
-{
- return d_func()->geometryInputType;
-}
-
-
-/*!
- Sets the output type from the geometry shader, if active, to
- \a outputType.
-
- This parameter takes effect the next time the program is linked.
-
- \since 4.7
-*/
-void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
-{
- d_func()->geometryOutputType = outputType;
-}
-
-
-/*!
- Returns the geometry shader output type, if active.
-
- This parameter takes effect the next time the program is linked.
-
- \since 4.7
- */
-GLenum QGLShaderProgram::geometryOutputType() const
-{
- return d_func()->geometryOutputType;
-}
-
-
-/*!
- Returns \c true if shader programs written in the OpenGL Shading
- Language (GLSL) are supported on this system; false otherwise.
-
- The \a context is used to resolve the GLSL extensions.
- If \a context is \nullptr, then QGLContext::currentContext() is
- used.
-*/
-bool QGLShaderProgram::hasOpenGLShaderPrograms(const QGLContext *context)
-{
-#if !defined(QT_OPENGL_ES_2)
- if (!context)
- context = QGLContext::currentContext();
- if (!context)
- return false;
-
- QOpenGLFunctions functions(context->contextHandle());
- return functions.hasOpenGLFeature(QOpenGLFunctions::Shaders);
-#else
- Q_UNUSED(context);
- return true;
-#endif
-}
-
-/*!
- \internal
-*/
-void QGLShaderProgram::shaderDestroyed()
-{
- Q_D(QGLShaderProgram);
- QGLShader *shader = qobject_cast<QGLShader *>(sender());
- if (shader && !d->removingShaders)
- removeShader(shader);
-}
-
-
-#undef ctx
-#undef context
-
-/*!
- Returns \c true if shader programs of type \a type are supported on
- this system; false otherwise.
-
- The \a context is used to resolve the GLSL extensions.
- If \a context is \nullptr, then QGLContext::currentContext() is
- used.
-
- \since 4.7
-*/
-bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
-{
- if (!context)
- context = QGLContext::currentContext();
- if (!context)
- return false;
-
- if ((type & ~(Geometry | Vertex | Fragment)) || type == 0)
- return false;
-
- QOpenGLFunctions functions(context->contextHandle());
- bool resolved = functions.hasOpenGLFeature(QOpenGLFunctions::Shaders);
- if (!resolved)
- return false;
-
- if ((type & Geometry) && !QByteArray((const char *) functions.glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
- return false;
-
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
deleted file mode 100644
index 3ce88197d2..0000000000
--- a/src/opengl/qglshaderprogram.h
+++ /dev/null
@@ -1,303 +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 QGLSHADERPROGRAM_H
-#define QGLSHADERPROGRAM_H
-
-#include <QtOpenGL/qgl.h>
-#include <QtGui/qvector2d.h>
-#include <QtGui/qvector3d.h>
-#include <QtGui/qvector4d.h>
-#include <QtGui/qmatrix4x4.h>
-
-QT_BEGIN_NAMESPACE
-
-
-class QGLShaderProgram;
-class QGLShaderPrivate;
-
-class Q_OPENGL_EXPORT QGLShader : public QObject
-{
- Q_OBJECT
-public:
- enum ShaderTypeBit
- {
- Vertex = 0x0001,
- Fragment = 0x0002,
- Geometry = 0x0004
- };
- Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
-
- explicit QGLShader(QGLShader::ShaderType type, QObject *parent = nullptr);
- QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = nullptr);
- virtual ~QGLShader();
-
- QGLShader::ShaderType shaderType() const;
-
- bool compileSourceCode(const char *source);
- bool compileSourceCode(const QByteArray& source);
- bool compileSourceCode(const QString& source);
- bool compileSourceFile(const QString& fileName);
-
- QByteArray sourceCode() const;
-
- bool isCompiled() const;
- QString log() const;
-
- GLuint shaderId() const;
-
- static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = nullptr);
-
-private:
- friend class QGLShaderProgram;
-
- Q_DISABLE_COPY(QGLShader)
- Q_DECLARE_PRIVATE(QGLShader)
-};
-
-Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType)
-
-
-class QGLShaderProgramPrivate;
-
-class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
-{
- Q_OBJECT
-public:
- explicit QGLShaderProgram(QObject *parent = nullptr);
- explicit QGLShaderProgram(const QGLContext *context, QObject *parent = nullptr);
- virtual ~QGLShaderProgram();
-
- bool addShader(QGLShader *shader);
- void removeShader(QGLShader *shader);
- QList<QGLShader *> shaders() const;
-
- bool addShaderFromSourceCode(QGLShader::ShaderType type, const char *source);
- bool addShaderFromSourceCode(QGLShader::ShaderType type, const QByteArray& source);
- bool addShaderFromSourceCode(QGLShader::ShaderType type, const QString& source);
- bool addShaderFromSourceFile(QGLShader::ShaderType type, const QString& fileName);
-
- void removeAllShaders();
-
- virtual bool link();
- bool isLinked() const;
- QString log() const;
-
- bool bind();
- void release();
-
- GLuint programId() const;
-
- int maxGeometryOutputVertices() const;
-
- void setGeometryOutputVertexCount(int count);
- int geometryOutputVertexCount() const;
-
- void setGeometryInputType(GLenum inputType);
- GLenum geometryInputType() const;
-
- void setGeometryOutputType(GLenum outputType);
- GLenum geometryOutputType() const;
-
- void bindAttributeLocation(const char *name, int location);
- void bindAttributeLocation(const QByteArray& name, int location);
- void bindAttributeLocation(const QString& name, int location);
-
- int attributeLocation(const char *name) const;
- int attributeLocation(const QByteArray& name) const;
- int attributeLocation(const QString& name) const;
-
- void setAttributeValue(int location, GLfloat value);
- void setAttributeValue(int location, GLfloat x, GLfloat y);
- void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z);
- void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void setAttributeValue(int location, const QVector2D& value);
- void setAttributeValue(int location, const QVector3D& value);
- void setAttributeValue(int location, const QVector4D& value);
- void setAttributeValue(int location, const QColor& value);
- void setAttributeValue(int location, const GLfloat *values, int columns, int rows);
-
- void setAttributeValue(const char *name, GLfloat value);
- void setAttributeValue(const char *name, GLfloat x, GLfloat y);
- void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
- void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void setAttributeValue(const char *name, const QVector2D& value);
- void setAttributeValue(const char *name, const QVector3D& value);
- void setAttributeValue(const char *name, const QVector4D& value);
- void setAttributeValue(const char *name, const QColor& value);
- void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows);
-
- void setAttributeArray
- (int location, const GLfloat *values, int tupleSize, int stride = 0);
- void setAttributeArray
- (int location, const QVector2D *values, int stride = 0);
- void setAttributeArray
- (int location, const QVector3D *values, int stride = 0);
- void setAttributeArray
- (int location, const QVector4D *values, int stride = 0);
- void setAttributeArray
- (int location, GLenum type, const void *values, int tupleSize, int stride = 0);
- void setAttributeArray
- (const char *name, const GLfloat *values, int tupleSize, int stride = 0);
- void setAttributeArray
- (const char *name, const QVector2D *values, int stride = 0);
- void setAttributeArray
- (const char *name, const QVector3D *values, int stride = 0);
- void setAttributeArray
- (const char *name, const QVector4D *values, int stride = 0);
- void setAttributeArray
- (const char *name, GLenum type, const void *values, int tupleSize, int stride = 0);
-
- void setAttributeBuffer
- (int location, GLenum type, int offset, int tupleSize, int stride = 0);
- void setAttributeBuffer
- (const char *name, GLenum type, int offset, int tupleSize, int stride = 0);
-
- void enableAttributeArray(int location);
- void enableAttributeArray(const char *name);
- void disableAttributeArray(int location);
- void disableAttributeArray(const char *name);
-
- int uniformLocation(const char *name) const;
- int uniformLocation(const QByteArray& name) const;
- int uniformLocation(const QString& name) const;
-
- void setUniformValue(int location, GLfloat value);
- void setUniformValue(int location, GLint value);
- void setUniformValue(int location, GLuint value);
- void setUniformValue(int location, GLfloat x, GLfloat y);
- void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z);
- void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void setUniformValue(int location, const QVector2D& value);
- void setUniformValue(int location, const QVector3D& value);
- void setUniformValue(int location, const QVector4D& value);
- void setUniformValue(int location, const QColor& color);
- void setUniformValue(int location, const QPoint& point);
- void setUniformValue(int location, const QPointF& point);
- void setUniformValue(int location, const QSize& size);
- void setUniformValue(int location, const QSizeF& size);
- void setUniformValue(int location, const QMatrix2x2& value);
- void setUniformValue(int location, const QMatrix2x3& value);
- void setUniformValue(int location, const QMatrix2x4& value);
- void setUniformValue(int location, const QMatrix3x2& value);
- void setUniformValue(int location, const QMatrix3x3& value);
- void setUniformValue(int location, const QMatrix3x4& value);
- void setUniformValue(int location, const QMatrix4x2& value);
- void setUniformValue(int location, const QMatrix4x3& value);
- void setUniformValue(int location, const QMatrix4x4& value);
- void setUniformValue(int location, const GLfloat value[2][2]);
- void setUniformValue(int location, const GLfloat value[3][3]);
- void setUniformValue(int location, const GLfloat value[4][4]);
- void setUniformValue(int location, const QTransform& value);
-
- void setUniformValue(const char *name, GLfloat value);
- void setUniformValue(const char *name, GLint value);
- void setUniformValue(const char *name, GLuint value);
- void setUniformValue(const char *name, GLfloat x, GLfloat y);
- void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
- void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
- void setUniformValue(const char *name, const QVector2D& value);
- void setUniformValue(const char *name, const QVector3D& value);
- void setUniformValue(const char *name, const QVector4D& value);
- void setUniformValue(const char *name, const QColor& color);
- void setUniformValue(const char *name, const QPoint& point);
- void setUniformValue(const char *name, const QPointF& point);
- void setUniformValue(const char *name, const QSize& size);
- void setUniformValue(const char *name, const QSizeF& size);
- void setUniformValue(const char *name, const QMatrix2x2& value);
- void setUniformValue(const char *name, const QMatrix2x3& value);
- void setUniformValue(const char *name, const QMatrix2x4& value);
- void setUniformValue(const char *name, const QMatrix3x2& value);
- void setUniformValue(const char *name, const QMatrix3x3& value);
- void setUniformValue(const char *name, const QMatrix3x4& value);
- void setUniformValue(const char *name, const QMatrix4x2& value);
- void setUniformValue(const char *name, const QMatrix4x3& value);
- void setUniformValue(const char *name, const QMatrix4x4& value);
- void setUniformValue(const char *name, const GLfloat value[2][2]);
- void setUniformValue(const char *name, const GLfloat value[3][3]);
- void setUniformValue(const char *name, const GLfloat value[4][4]);
- void setUniformValue(const char *name, const QTransform& value);
-
- void setUniformValueArray(int location, const GLfloat *values, int count, int tupleSize);
- void setUniformValueArray(int location, const GLint *values, int count);
- void setUniformValueArray(int location, const GLuint *values, int count);
- void setUniformValueArray(int location, const QVector2D *values, int count);
- void setUniformValueArray(int location, const QVector3D *values, int count);
- void setUniformValueArray(int location, const QVector4D *values, int count);
- void setUniformValueArray(int location, const QMatrix2x2 *values, int count);
- void setUniformValueArray(int location, const QMatrix2x3 *values, int count);
- void setUniformValueArray(int location, const QMatrix2x4 *values, int count);
- void setUniformValueArray(int location, const QMatrix3x2 *values, int count);
- void setUniformValueArray(int location, const QMatrix3x3 *values, int count);
- void setUniformValueArray(int location, const QMatrix3x4 *values, int count);
- void setUniformValueArray(int location, const QMatrix4x2 *values, int count);
- void setUniformValueArray(int location, const QMatrix4x3 *values, int count);
- void setUniformValueArray(int location, const QMatrix4x4 *values, int count);
-
- void setUniformValueArray(const char *name, const GLfloat *values, int count, int tupleSize);
- void setUniformValueArray(const char *name, const GLint *values, int count);
- void setUniformValueArray(const char *name, const GLuint *values, int count);
- void setUniformValueArray(const char *name, const QVector2D *values, int count);
- void setUniformValueArray(const char *name, const QVector3D *values, int count);
- void setUniformValueArray(const char *name, const QVector4D *values, int count);
- void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count);
- void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count);
-
- static bool hasOpenGLShaderPrograms(const QGLContext *context = nullptr);
-
-private Q_SLOTS:
- void shaderDestroyed();
-
-private:
- Q_DISABLE_COPY(QGLShaderProgram)
- Q_DECLARE_PRIVATE(QGLShaderProgram)
-
- bool init();
-};
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp
deleted file mode 100644
index 97b83a6b3d..0000000000
--- a/src/opengl/qgraphicsshadereffect.cpp
+++ /dev/null
@@ -1,272 +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 "qgraphicsshadereffect_p.h"
-
-#include "qglshaderprogram.h"
-#include "gl2paintengineex/qglcustomshaderstage_p.h"
-#define QGL_HAVE_CUSTOM_SHADERS 1
-#include <QtGui/qpainter.h>
-#include <QtWidgets/qgraphicsitem.h>
-#include <private/qgraphicseffect_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*#
- \class QGraphicsShaderEffect
- \inmodule QtOpenGL
- \brief The QGraphicsShaderEffect class is the base class for creating
- custom GLSL shader effects in a QGraphicsScene.
- \since 4.6
- \ingroup multimedia
- \ingroup graphicsview-api
-
- The specific effect is defined by a fragment of GLSL source code
- supplied to setPixelShaderFragment(). This source code must define a
- function with the signature
- \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)}
- that returns the source pixel value
- to use in the paint engine's shader program. The shader fragment
- is linked with the regular shader code used by the GL2 paint engine
- to construct a complete QGLShaderProgram.
-
- The following example shader converts the incoming pixmap to
- grayscale and then applies a colorize operation using the
- \c effectColor value:
-
- \snippet code/src_opengl_qgraphicsshadereffect.cpp 0
-
- To use this shader code, it is necessary to define a subclass
- of QGraphicsShaderEffect as follows:
-
- \snippet code/src_opengl_qgraphicsshadereffect.cpp 1
-
- The setUniforms() function is called when the effect is about
- to be used for drawing to give the subclass the opportunity to
- set effect-specific uniform variables.
-
- QGraphicsShaderEffect is only supported when the GL2 paint engine
- is in use. When any other paint engine is in use (GL1, raster, etc),
- the drawItem() method will draw its item argument directly with
- no effect applied.
-
- \sa QGraphicsEffect
-*/
-
-static const char qglslDefaultImageFragmentShader[] = "\
- lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { \
- return texture2D(imageTexture, textureCoords); \
- }\n";
-
-#ifdef QGL_HAVE_CUSTOM_SHADERS
-
-class QGLCustomShaderEffectStage : public QGLCustomShaderStage
-{
-public:
- QGLCustomShaderEffectStage
- (QGraphicsShaderEffect *e, const QByteArray& source)
- : QGLCustomShaderStage(),
- effect(e)
- {
- setSource(source);
- }
-
- void setUniforms(QGLShaderProgram *program) override;
-
- QGraphicsShaderEffect *effect;
-};
-
-void QGLCustomShaderEffectStage::setUniforms(QGLShaderProgram *program)
-{
- effect->setUniforms(program);
-}
-
-#endif
-
-class QGraphicsShaderEffectPrivate : public QGraphicsEffectPrivate
-{
- Q_DECLARE_PUBLIC(QGraphicsShaderEffect)
-public:
- QGraphicsShaderEffectPrivate()
- : pixelShaderFragment(qglslDefaultImageFragmentShader)
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- , customShaderStage(0)
-#endif
- {
- }
-
- QByteArray pixelShaderFragment;
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- QGLCustomShaderEffectStage *customShaderStage;
-#endif
-};
-
-/*#
- Constructs a shader effect and attaches it to \a parent.
-*/
-QGraphicsShaderEffect::QGraphicsShaderEffect(QObject *parent)
- : QGraphicsEffect(*new QGraphicsShaderEffectPrivate(), parent)
-{
-}
-
-/*#
- Destroys this shader effect.
-*/
-QGraphicsShaderEffect::~QGraphicsShaderEffect()
-{
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- Q_D(QGraphicsShaderEffect);
- delete d->customShaderStage;
-#endif
-}
-
-/*#
- Returns the source code for the pixel shader fragment for
- this shader effect. The default is a shader that copies
- its incoming pixmap directly to the output with no effect
- applied.
-
- \sa setPixelShaderFragment()
-*/
-QByteArray QGraphicsShaderEffect::pixelShaderFragment() const
-{
- Q_D(const QGraphicsShaderEffect);
- return d->pixelShaderFragment;
-}
-
-/*#
- Sets the source code for the pixel shader fragment for
- this shader effect to \a code.
-
- The \a code must define a GLSL function with the signature
- \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)}
- that returns the source pixel value to use in the paint engine's
- shader program. The following is the default pixel shader fragment,
- which draws a pixmap with no effect applied:
-
- \snippet code/src_opengl_qgraphicsshadereffect.cpp 2
-
- \sa pixelShaderFragment(), setUniforms()
-*/
-void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code)
-{
- Q_D(QGraphicsShaderEffect);
- if (d->pixelShaderFragment != code) {
- d->pixelShaderFragment = code;
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- delete d->customShaderStage;
- d->customShaderStage = 0;
-#endif
- }
-}
-
-/*#
- \reimp
-*/
-void QGraphicsShaderEffect::draw(QPainter *painter)
-{
- Q_D(QGraphicsShaderEffect);
-
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- // Set the custom shader on the paint engine. The setOnPainter()
- // call may fail if the paint engine is not GL2. In that case,
- // we fall through to drawing the pixmap normally.
- if (!d->customShaderStage) {
- d->customShaderStage = new QGLCustomShaderEffectStage
- (this, d->pixelShaderFragment);
- }
- bool usingShader = d->customShaderStage->setOnPainter(painter);
-
- QPoint offset;
- if (sourceIsPixmap()) {
- // No point in drawing in device coordinates (pixmap will be scaled anyways).
- const QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset);
- painter->drawPixmap(offset, pixmap);
- } else {
- // Draw pixmap in device coordinates to avoid pixmap scaling.
- const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset);
- QTransform restoreTransform = painter->worldTransform();
- painter->setWorldTransform(QTransform());
- painter->drawPixmap(offset, pixmap);
- painter->setWorldTransform(restoreTransform);
- }
-
- // Remove the custom shader to return to normal painting operations.
- if (usingShader)
- d->customShaderStage->removeFromPainter(painter);
-#else
- drawSource(painter);
-#endif
-}
-
-/*#
- Sets the custom uniform variables on this shader effect to
- be dirty. The setUniforms() function will be called the next
- time the shader program corresponding to this effect is used.
-
- This function is typically called by subclasses when an
- effect-specific parameter is changed by the application.
-
- \sa setUniforms()
-*/
-void QGraphicsShaderEffect::setUniformsDirty()
-{
-#ifdef QGL_HAVE_CUSTOM_SHADERS
- Q_D(QGraphicsShaderEffect);
- if (d->customShaderStage)
- d->customShaderStage->setUniformsDirty();
-#endif
-}
-
-/*#
- Sets custom uniform variables on the current GL context when
- \a program is about to be used by the paint engine.
-
- This function should be overridden if the shader set with
- setPixelShaderFragment() has additional parameters beyond
- those that the paint engine normally sets itself.
-
- \sa setUniformsDirty()
-*/
-void QGraphicsShaderEffect::setUniforms(QGLShaderProgram *program)
-{
- Q_UNUSED(program);
-}
-
-QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/qopengl2pexvertexarray.cpp
index 979ea19fee..df0fb764c9 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
+++ b/src/opengl/qopengl2pexvertexarray.cpp
@@ -37,13 +37,13 @@
**
****************************************************************************/
-#include "qgl2pexvertexarray_p.h"
+#include "qopengl2pexvertexarray_p.h"
#include <private/qbezier_p.h>
QT_BEGIN_NAMESPACE
-void QGL2PEXVertexArray::clear()
+void QOpenGL2PEXVertexArray::clear()
{
vertexArray.reset();
vertexArrayStops.reset();
@@ -51,22 +51,22 @@ void QGL2PEXVertexArray::clear()
}
-QGLRect QGL2PEXVertexArray::boundingRect() const
+QOpenGLRect QOpenGL2PEXVertexArray::boundingRect() const
{
if (boundingRectDirty)
- return QGLRect(0.0, 0.0, 0.0, 0.0);
+ return QOpenGLRect(0.0, 0.0, 0.0, 0.0);
else
- return QGLRect(minX, minY, maxX, maxY);
+ return QOpenGLRect(minX, minY, maxX, maxY);
}
-void QGL2PEXVertexArray::addClosingLine(int index)
+void QOpenGL2PEXVertexArray::addClosingLine(int index)
{
QPointF point(vertexArray.at(index));
if (point != QPointF(vertexArray.last()))
vertexArray.add(point);
}
-void QGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
+void QOpenGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
{
const QPointF *const points = reinterpret_cast<const QPointF *>(path.points());
const QPainterPath::ElementType *const elements = path.elements();
@@ -83,7 +83,7 @@ void QGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
vertexArray.add(centroid);
}
-void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline)
+void QOpenGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline)
{
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
const QPainterPath::ElementType* const elements = path.elements();
@@ -156,9 +156,9 @@ void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseSc
vertexArrayStops.add(vertexArray.size());
}
-void QGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y)
+void QOpenGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y)
{
- vertexArray.add(QGLPoint(x, y));
+ vertexArray.add(QOpenGLPoint(x, y));
if (x > maxX)
maxX = x;
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/qopengl2pexvertexarray_p.h
index 5c95268790..3ef26e908d 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+++ b/src/opengl/qopengl2pexvertexarray_p.h
@@ -48,27 +48,27 @@
// We mean it.
//
-#ifndef QGL2PEXVERTEXARRAY_P_H
-#define QGL2PEXVERTEXARRAY_P_H
+#ifndef QOPENGL2PEXVERTEXARRAY_P_H
+#define QOPENGL2PEXVERTEXARRAY_P_H
#include <QRectF>
#include <private/qdatabuffer_p.h>
#include <private/qvectorpath_p.h>
-#include <private/qgl_p.h>
+#include <private/qopenglcontext_p.h>
QT_BEGIN_NAMESPACE
-class QGLPoint
+class QOpenGLPoint
{
public:
- QGLPoint(GLfloat new_x, GLfloat new_y) :
+ QOpenGLPoint(GLfloat new_x, GLfloat new_y) :
x(new_x), y(new_y) {};
- QGLPoint(const QPointF &p) :
+ QOpenGLPoint(const QPointF &p) :
x(p.x()), y(p.y()) {};
- QGLPoint(const QPointF* p) :
+ QOpenGLPoint(const QPointF* p) :
x(p->x()), y(p->y()) {};
GLfloat x;
@@ -78,12 +78,12 @@ public:
operator QPointF() const {return QPointF(x,y);}
};
-struct QGLRect
+struct QOpenGLRect
{
- QGLRect(const QRectF &r)
+ QOpenGLRect(const QRectF &r)
: left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
- QGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
+ QOpenGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
: left(l), top(t), right(r), bottom(b) {}
GLfloat left;
@@ -94,10 +94,10 @@ struct QGLRect
operator QRectF() const {return QRectF(left, top, right-left, bottom-top);}
};
-class QGL2PEXVertexArray
+class QOpenGL2PEXVertexArray
{
public:
- QGL2PEXVertexArray() :
+ QOpenGL2PEXVertexArray() :
vertexArray(0), vertexArrayStops(0),
maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
boundingRectDirty(true)
@@ -110,12 +110,12 @@ public:
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);
+ vertexArray << QOpenGLPoint(left, top)
+ << QOpenGLPoint(right, top)
+ << QOpenGLPoint(right, bottom)
+ << QOpenGLPoint(right, bottom)
+ << QOpenGLPoint(left, bottom)
+ << QOpenGLPoint(left, top);
}
inline void addQuad(const QRectF &rect)
@@ -125,32 +125,32 @@ public:
qreal bottom = rect.bottom();
qreal right = rect.right();
- vertexArray << QGLPoint(left, top)
- << QGLPoint(right, top)
- << QGLPoint(left, bottom)
- << QGLPoint(right, bottom);
+ vertexArray << QOpenGLPoint(left, top)
+ << QOpenGLPoint(right, top)
+ << QOpenGLPoint(left, bottom)
+ << QOpenGLPoint(right, bottom);
}
inline void addVertex(const GLfloat x, const GLfloat y)
{
- vertexArray.add(QGLPoint(x, y));
+ vertexArray.add(QOpenGLPoint(x, y));
}
void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
void clear();
- QGLPoint* data() {return vertexArray.data();}
+ QOpenGLPoint* data() {return vertexArray.data();}
int *stops() const { return vertexArrayStops.data(); }
int stopCount() const { return vertexArrayStops.size(); }
- QGLRect boundingRect() const;
+ QOpenGLRect boundingRect() const;
int vertexCount() const { return vertexArray.size(); }
void lineToArray(const GLfloat x, const GLfloat y);
private:
- QDataBuffer<QGLPoint> vertexArray;
+ QDataBuffer<QOpenGLPoint> vertexArray;
QDataBuffer<int> vertexArrayStops;
GLfloat maxX;
diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp b/src/opengl/qopenglcustomshaderstage.cpp
index 7d6d4595ba..7a32b2fbc0 100644
--- a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp
+++ b/src/opengl/qopenglcustomshaderstage.cpp
@@ -37,34 +37,34 @@
**
****************************************************************************/
-#include "qglcustomshaderstage_p.h"
-#include "qglengineshadermanager_p.h"
-#include "qpaintengineex_opengl2_p.h"
+#include "qopenglcustomshaderstage_p.h"
+#include "qopenglengineshadermanager_p.h"
+#include "qopenglpaintengine_p.h"
#include <private/qpainter_p.h>
QT_BEGIN_NAMESPACE
-class QGLCustomShaderStagePrivate
+class QOpenGLCustomShaderStagePrivate
{
public:
- QGLCustomShaderStagePrivate() :
- m_manager(0) {}
+ QOpenGLCustomShaderStagePrivate() :
+ m_manager(nullptr) {}
- QPointer<QGLEngineShaderManager> m_manager;
+ QPointer<QOpenGLEngineShaderManager> m_manager;
QByteArray m_source;
};
-QGLCustomShaderStage::QGLCustomShaderStage()
- : d_ptr(new QGLCustomShaderStagePrivate)
+QOpenGLCustomShaderStage::QOpenGLCustomShaderStage()
+ : d_ptr(new QOpenGLCustomShaderStagePrivate)
{
}
-QGLCustomShaderStage::~QGLCustomShaderStage()
+QOpenGLCustomShaderStage::~QOpenGLCustomShaderStage()
{
- Q_D(QGLCustomShaderStage);
+ Q_D(QOpenGLCustomShaderStage);
if (d->m_manager) {
d->m_manager->removeCustomStage();
d->m_manager->sharedShaders->cleanupCustomStage(this);
@@ -72,65 +72,65 @@ QGLCustomShaderStage::~QGLCustomShaderStage()
delete d_ptr;
}
-void QGLCustomShaderStage::setUniformsDirty()
+void QOpenGLCustomShaderStage::setUniformsDirty()
{
- Q_D(QGLCustomShaderStage);
+ Q_D(QOpenGLCustomShaderStage);
if (d->m_manager)
d->m_manager->setDirty(); // ### Probably a bit overkill!
}
-bool QGLCustomShaderStage::setOnPainter(QPainter* p)
+bool QOpenGLCustomShaderStage::setOnPainter(QPainter* p)
{
- Q_D(QGLCustomShaderStage);
+ Q_D(QOpenGLCustomShaderStage);
if (p->paintEngine()->type() != QPaintEngine::OpenGL2) {
- qWarning("QGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2");
+ qWarning("QOpenGLCustomShaderStage::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);
+ QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine());
+ d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
Q_ASSERT(d->m_manager);
d->m_manager->setCustomStage(this);
return true;
}
-void QGLCustomShaderStage::removeFromPainter(QPainter* p)
+void QOpenGLCustomShaderStage::removeFromPainter(QPainter* p)
{
- Q_D(QGLCustomShaderStage);
+ Q_D(QOpenGLCustomShaderStage);
if (p->paintEngine()->type() != QPaintEngine::OpenGL2)
return;
- QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx*>(p->paintEngine());
- d->m_manager = QGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
+ QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine());
+ d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
Q_ASSERT(d->m_manager);
// Just set the stage to null, don't call removeCustomStage().
// This should leave the program in a compiled/linked state
// if the next custom shader stage is this one again.
- d->m_manager->setCustomStage(0);
- d->m_manager = 0;
+ d->m_manager->setCustomStage(nullptr);
+ d->m_manager = nullptr;
}
-QByteArray QGLCustomShaderStage::source() const
+QByteArray QOpenGLCustomShaderStage::source() const
{
- Q_D(const QGLCustomShaderStage);
+ Q_D(const QOpenGLCustomShaderStage);
return d->m_source;
}
// Called by the shader manager if another custom shader is attached or
// the manager is deleted
-void QGLCustomShaderStage::setInactive()
+void QOpenGLCustomShaderStage::setInactive()
{
- Q_D(QGLCustomShaderStage);
- d->m_manager = 0;
+ Q_D(QOpenGLCustomShaderStage);
+ d->m_manager = nullptr;
}
-void QGLCustomShaderStage::setSource(const QByteArray& s)
+void QOpenGLCustomShaderStage::setSource(const QByteArray& s)
{
- Q_D(QGLCustomShaderStage);
+ Q_D(QOpenGLCustomShaderStage);
d->m_source = s;
}
diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h b/src/opengl/qopenglcustomshaderstage_p.h
index 77421ebdd3..255c115e3c 100644
--- a/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h
+++ b/src/opengl/qopenglcustomshaderstage_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QGL_CUSTOM_SHADER_STAGE_H
-#define QGL_CUSTOM_SHADER_STAGE_H
+#ifndef QOPENGL_CUSTOM_SHADER_STAGE_H
+#define QOPENGL_CUSTOM_SHADER_STAGE_H
//
// W A R N I N G
@@ -51,19 +51,21 @@
// We mean it.
//
-#include <QGLShaderProgram>
+#include <QtOpenGL/qtopenglglobal.h>
+#include <QOpenGLShaderProgram>
QT_BEGIN_NAMESPACE
-class QGLCustomShaderStagePrivate;
-class Q_OPENGL_EXPORT QGLCustomShaderStage
+class QPainter;
+class QOpenGLCustomShaderStagePrivate;
+class Q_OPENGL_EXPORT QOpenGLCustomShaderStage
{
- Q_DECLARE_PRIVATE(QGLCustomShaderStage)
+ Q_DECLARE_PRIVATE(QOpenGLCustomShaderStage)
public:
- QGLCustomShaderStage();
- virtual ~QGLCustomShaderStage();
- virtual void setUniforms(QGLShaderProgram*) {}
+ QOpenGLCustomShaderStage();
+ virtual ~QOpenGLCustomShaderStage();
+ virtual void setUniforms(QOpenGLShaderProgram*) {}
void setUniformsDirty();
@@ -76,7 +78,9 @@ protected:
void setSource(const QByteArray&);
private:
- QGLCustomShaderStagePrivate* d_ptr;
+ QOpenGLCustomShaderStagePrivate* d_ptr;
+
+ Q_DISABLE_COPY_MOVE(QOpenGLCustomShaderStage)
};
diff --git a/src/opengl/qopengldebug.cpp b/src/opengl/qopengldebug.cpp
new file mode 100644
index 0000000000..a69f6069dc
--- /dev/null
+++ b/src/opengl/qopengldebug.cpp
@@ -0,0 +1,1826 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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 <QtCore/private/qobject_p.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qopengl.h>
+#include <QtGui/qopenglfunctions.h>
+#include <QtGui/qoffscreensurface.h>
+
+#include "qopengldebug.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLDebugMessage
+ \brief The QOpenGLDebugMessage class wraps an OpenGL debug message.
+ \inmodule QtOpenGL
+ \reentrant
+ \since 5.1
+ \ingroup shared
+ \ingroup painting-3D
+
+ Debug messages are usually created by the OpenGL server and then read by
+ OpenGL clients (either from the OpenGL internal debug log, or logged in real-time).
+ A debug message has a textual representation, a vendor-specific numeric id,
+ a source, a type and a severity.
+
+ It's also possible for applications or third-party libraries and toolkits
+ to create and insert messages in the debug log. In order to do so, you can use
+ the createApplicationMessage() or the createThirdPartyMessage() static functions.
+
+ \sa QOpenGLDebugLogger
+*/
+
+/*!
+ \class QOpenGLDebugLogger
+ \brief The QOpenGLDebugLogger enables logging of OpenGL debugging messages.
+ \inmodule QtOpenGL
+ \since 5.1
+ \ingroup painting-3D
+
+ \tableofcontents
+
+ \section1 Introduction
+
+ OpenGL programming can be very error prone. Most of the time, a single
+ failing call to OpenGL can cause an entire portion of an application to
+ stop working, with nothing being drawn on the screen.
+
+ The only way to be sure that no errors are being returned from the OpenGL
+ implementation is checking with \c{glGetError} after each and every API
+ call. Moreover, OpenGL errors stack up, therefore glGetError should always
+ be used in a loop like this:
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 0
+
+ If you try to clear the error stack, make sure not just keep going until
+ GL_NO_ERROR is returned but also break on GL_CONTEXT_LOST as that error
+ value will keep repeating.
+
+ There are also many other information we are interested in (as application
+ developers), for instance performance issues, or warnings about using
+ deprecated APIs. Those kind of messages are not reported through the
+ ordinary OpenGL error reporting mechanisms.
+
+ QOpenGLDebugLogger aims at addressing these issues by providing access to
+ the \e{OpenGL debug log}. If your OpenGL implementation supports it (by
+ exposing the \c{GL_KHR_debug} extension), messages from the OpenGL server
+ will be either logged in an internal OpenGL log, or passed in "real-time"
+ to listeners as they're generated from OpenGL.
+
+ QOpenGLDebugLogger supports both these modes of operation. Refer to the
+ following sections to find out the differences between them.
+
+ \section1 Creating an OpenGL Debug Context
+
+ For efficiency reasons, OpenGL implementations are allowed not to create
+ any debug output at all, unless the OpenGL context is a debug context. In order
+ to create a debug context from Qt, you must set the QSurfaceFormat::DebugContext
+ format option on the QSurfaceFormat used to create the QOpenGLContext object:
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 1
+
+ Note that requesting a 3.2 OpenGL Core Profile is just for the example's
+ purposes; this class is not tied to any specific OpenGL or OpenGL ES
+ version, as it relies on the availability of the \c{GL_KHR_debug} extension
+ (see below).
+
+ \section1 Creating and Initializing a QOpenGLDebugLogger
+
+ QOpenGLDebugLogger is a simple QObject-derived class. Just like all QObject
+ subclasses, you create an instance (and optionally specify a parent
+ object), and like the other OpenGL functions in Qt you \e{must} initialize
+ it before usage by calling initialize() whilst there is a current OpenGL context:
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 2
+
+ Note that the \c{GL_KHR_debug} extension \e{must} be available in the context
+ in order to access the messages logged by OpenGL. You can check the
+ presence of this extension by calling:
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 3
+
+ where \c{ctx} is a valid QOpenGLContext. If the extension is not available,
+ initialize() will return false.
+
+ \section1 Reading the Internal OpenGL Debug Log
+
+ OpenGL implementations keep an internal log of debug messages. Messages
+ stored in this log can be retrieved by using the loggedMessages() function:
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 4
+
+ The internal log has a limited size; when it fills up, older messages will
+ get discarded to make room for the new incoming messages. When you call
+ loggedMessages(), the internal log will be emptied as well.
+
+ If you want to be sure not to lose any debug message, you must use real-time
+ logging instead of calling this function. However, debug messages might
+ still be generated in the timespan between context creation and activation
+ of real-time logging (or, in general, when the real-time logging is disabled).
+
+ \section1 Real-time logging of messages
+
+ It is also possible to receive a stream of debug messages from the OpenGL
+ server \e{as they are generated} by the implementation. In order to do so,
+ you need to connect a suitable slot to the messageLogged() signal, and
+ start logging by calling startLogging():
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 5
+
+ Similarly, logging can be disabled at any time by calling the stopLogging()
+ function.
+
+ Real-time logging can be either asynchronous or synchronous, depending on
+ the parameter passed to startLogging(). When logging in asynchronous mode
+ (the default, as it has a very small overhead), the OpenGL implementation
+ can generate messages at any time, and/or in an order which is different from the
+ order of the OpenGL commands which caused those messages to be logged.
+ The messages could also be generated from a thread that it's different from
+ the thread the context is currently bound to. This is because OpenGL
+ implementations are usually highly threaded and asynchronous, and therefore
+ no warranties are made about the relative order and the timings of the
+ debug messages.
+
+ On the other hand, logging in synchronous mode has a high overhead, but
+ the OpenGL implementation guarantees that all the messages caused by a
+ certain command are received in order, before the command returns,
+ and from the same thread the OpenGL context is bound to.
+
+ This means that when logging in synchronous mode you will be able to run
+ your OpenGL application in a debugger, put a breakpoint on a slot connected
+ to the messageLogged() signal, and see in the backtrace the exact call
+ that caused the logged message. This can be extremely useful to debug
+ an OpenGL problem. Note that if OpenGL rendering is happening in another
+ thread, you must force the signal/slot connection type to Qt::DirectConnection
+ in order to be able to see the actual backtrace.
+
+ Refer to the LoggingMode enum documentation for more information about
+ logging modes.
+
+ \note When real-time logging is enabled, debug messages will \e{not} be
+ inserted in the internal OpenGL debug log any more; messages already
+ present in the internal log will not be deleted, nor they will be emitted
+ through the messageLogged() signal. Since some messages might be generated
+ before real-time logging is started (and therefore be kept in the internal
+ OpenGL log), it is important to always check if it contains any message
+ after calling startLogging().
+
+ \section1 Inserting Messages in the Debug Log
+
+ It is possible for applications and libraries to insert custom messages in
+ the debug log, for instance for marking a group of related OpenGL commands
+ and therefore being then able to identify eventual messages coming from them.
+
+ In order to do so, you can create a QOpenGLDebugMessage object by calling
+ \l{QOpenGLDebugMessage::}{createApplicationMessage()} or
+ \l{QOpenGLDebugMessage::}{createThirdPartyMessage()}, and then inserting it
+ into the log by calling logMessage():
+
+ \snippet code/src_gui_opengl_qopengldebug.cpp 6
+
+ Note that OpenGL implementations have a vendor-specific limit to the length
+ of the messages that can be inserted in the debug log. You can retrieve
+ this length by calling the maximumMessageLength() method; messages longer
+ than the limit will automatically get truncated.
+
+ \section1 Controlling the Debug Output
+
+ QOpenGLDebugMessage is also able to apply filters to the debug messages, and
+ therefore limit the amount of messages logged. You can enable or disable
+ logging of messages by calling enableMessages() and disableMessages()
+ respectively. By default, all messages are logged.
+
+ It is possible to enable or disable messages by selecting them by:
+
+ \list
+ \li source, type and severity (and including all ids in the selection);
+ \li id, source and type (and including all severities in the selection).
+ \endlist
+
+ Note that the "enabled" status for a given message is a property of the
+ (id, source, type, severity) tuple; the message attributes \e{do not} form
+ a hierarchy of any kind. You should be careful about the order of the calls
+ to enableMessages() and disableMessages(), as it will change which
+ messages will are enabled / disabled.
+
+ It's not possible to filter by the message text itself; applications
+ have to do that on their own (in slots connected to the messageLogged()
+ signal, or after fetching the messages in the internal debug log
+ through loggedMessages()).
+
+ In order to simplify the management of the enabled / disabled statuses,
+ QOpenGLDebugMessage also supports the concept of \c{debug groups}. A debug
+ group contains the group of enabled / disabled configurations of debug
+ messages. Moreover, debug groups are organized in a stack: it is possible
+ to push and pop groups by calling pushGroup() and popGroup() respectively.
+ (When an OpenGL context is created, there is already a group in the stack).
+
+ The enableMessages() and disableMessages() functions will modify the
+ configuration in the current debug group, that is, the one at the top of
+ the debug groups stack.
+
+ When a new group is pushed onto the debug groups stack, it will inherit
+ the configuration of the group that was previously on the top of the stack.
+ Vice versa, popping a debug group will restore the configuration of
+ the debug group that becomes the new top.
+
+ Pushing (respectively popping) debug groups will also automatically generate
+ a debug message of type QOpenGLDebugMessage::GroupPushType (respectively
+ \l{QOpenGLDebugMessage::}{GroupPopType}).
+
+ \sa QOpenGLDebugMessage
+*/
+
+/*!
+ \enum QOpenGLDebugMessage::Source
+
+ The Source enum defines the source of the debug message.
+
+ \value InvalidSource
+ The source of the message is invalid; this is the source of a
+ default-constructed QOpenGLDebugMessage object.
+
+ \value APISource
+ The message was generated in response to OpenGL API calls.
+
+ \value WindowSystemSource
+ The message was generated by the window system.
+
+ \value ShaderCompilerSource
+ The message was generated by the shader compiler.
+
+ \value ThirdPartySource
+ The message was generated by a third party, for instance an OpenGL
+ framework a or debugging toolkit.
+
+ \value ApplicationSource
+ The message was generated by the application itself.
+
+ \value OtherSource
+ The message was generated by a source not included in this
+ enumeration.
+
+ \omitvalue LastSource
+
+ \value AnySource
+ This value corresponds to a mask of all possible message sources.
+*/
+
+/*!
+ \enum QOpenGLDebugMessage::Type
+
+ The Type enum defines the type of the debug message.
+
+ \value InvalidType
+ The type of the message is invalid; this is the type of a
+ default-constructed QOpenGLDebugMessage object.
+
+ \value ErrorType
+ The message represents an error.
+
+ \value DeprecatedBehaviorType
+ The message represents an usage of deprecated behavior.
+
+ \value UndefinedBehaviorType
+ The message represents an usage of undefined behavior.
+
+ \value PortabilityType
+ The message represents an usage of vendor-specific behavior,
+ that might pose portability concerns.
+
+ \value PerformanceType
+ The message represents a performance issue.
+
+ \value OtherType
+ The message represents a type not included in this
+ enumeration.
+
+ \value MarkerType
+ The message represents a marker in the debug log.
+
+ \value GroupPushType
+ The message represents a debug group push operation.
+
+ \value GroupPopType
+ The message represents a debug group pop operation.
+
+ \omitvalue LastType
+
+ \value AnyType
+ This value corresponds to a mask of all possible message types.
+*/
+
+/*!
+ \enum QOpenGLDebugMessage::Severity
+
+ The Severity enum defines the severity of the debug message.
+
+ \value InvalidSeverity
+ The severity of the message is invalid; this is the severity of a
+ default-constructed QOpenGLDebugMessage object.
+
+ \value HighSeverity
+ The message has a high severity.
+
+ \value MediumSeverity
+ The message has a medium severity.
+
+ \value LowSeverity
+ The message has a low severity.
+
+ \value NotificationSeverity
+ The message is a notification.
+
+ \omitvalue LastSeverity
+
+ \value AnySeverity
+ This value corresponds to a mask of all possible message severities.
+*/
+
+/*!
+ \property QOpenGLDebugLogger::loggingMode
+
+ \brief the logging mode passed to startLogging().
+
+ Note that logging must have been started or the value of this property
+ will be meaningless.
+
+ \sa startLogging(), isLogging()
+*/
+/*!
+ \enum QOpenGLDebugLogger::LoggingMode
+
+ The LoggingMode enum defines the logging mode of the logger object.
+
+ \value AsynchronousLogging
+ Messages from the OpenGL server are logged asynchronously. This means
+ that messages can be logged some time after the corresponding OpenGL
+ actions that caused them, and even be received in an out-of-order
+ fashion, depending on the OpenGL implementation. This mode has a very low
+ performance penalty, as OpenGL implementations are heavily threaded
+ and asynchronous by nature.
+
+ \value SynchronousLogging
+ Messages from the OpenGL server are logged synchronously and
+ sequentially. This has a severe performance hit, as OpenGL
+ implementations are very asynchronous by nature; but it's very useful
+ to debug OpenGL problems, as OpenGL guarantees that the messages
+ generated by a OpenGL command will be logged before the corresponding
+ command execution has returned. Therefore, you can install a breakpoint
+ on the messageLogged() signal and see in the backtrace which OpenGL
+ command caused it; the only caveat is that if you are using OpenGL from
+ multiple threads you may need to force direct connection when
+ connecting to the messageLogged() signal.
+*/
+
+// When using OpenGL ES 2.0, all the necessary GL_KHR_debug constants are
+// provided in qopengles2ext.h. Unfortunately, newer versions of that file
+// suffix everything with _KHR which causes extra headache when the goal is
+// to have a single piece of code that builds in all our target
+// environments. Therefore, try to detect this and use our custom defines
+// instead, which we anyway need for OS X.
+
+#if defined(GL_KHR_debug) && defined(GL_DEBUG_SOURCE_API_KHR)
+#define USE_MANUAL_DEFS
+#endif
+
+// Under OSX (at least up to 10.8) we cannot include our copy of glext.h,
+// but we use the system-wide one, which unfortunately lacks all the needed
+// defines/typedefs. In order to make the code compile, we just add here
+// the GL_KHR_debug defines.
+
+#ifndef GL_KHR_debug
+#define GL_KHR_debug 1
+#define USE_MANUAL_DEFS
+#endif
+
+#ifdef USE_MANUAL_DEFS
+
+#ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#endif
+#ifndef GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#endif
+#ifndef GL_DEBUG_CALLBACK_FUNCTION
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#endif
+#ifndef GL_DEBUG_CALLBACK_USER_PARAM
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#endif
+#ifndef GL_DEBUG_SOURCE_API
+#define GL_DEBUG_SOURCE_API 0x8246
+#endif
+#ifndef GL_DEBUG_SOURCE_WINDOW_SYSTEM
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#endif
+#ifndef GL_DEBUG_SOURCE_SHADER_COMPILER
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#endif
+#ifndef GL_DEBUG_SOURCE_THIRD_PARTY
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#endif
+#ifndef GL_DEBUG_SOURCE_APPLICATION
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#endif
+#ifndef GL_DEBUG_SOURCE_OTHER
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#endif
+#ifndef GL_DEBUG_TYPE_ERROR
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#endif
+#ifndef GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#endif
+#ifndef GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#endif
+#ifndef GL_DEBUG_TYPE_PORTABILITY
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#endif
+#ifndef GL_DEBUG_TYPE_PERFORMANCE
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#endif
+#ifndef GL_DEBUG_TYPE_OTHER
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#endif
+#ifndef GL_DEBUG_TYPE_MARKER
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#endif
+#ifndef GL_DEBUG_TYPE_PUSH_GROUP
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#endif
+#ifndef GL_DEBUG_TYPE_POP_GROUP
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#endif
+#ifndef GL_DEBUG_SEVERITY_NOTIFICATION
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#endif
+#ifndef GL_MAX_DEBUG_GROUP_STACK_DEPTH
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#endif
+#ifndef GL_DEBUG_GROUP_STACK_DEPTH
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#endif
+#ifndef GL_BUFFER
+#define GL_BUFFER 0x82E0
+#endif
+#ifndef GL_SHADER
+#define GL_SHADER 0x82E1
+#endif
+#ifndef GL_PROGRAM
+#define GL_PROGRAM 0x82E2
+#endif
+#ifndef GL_QUERY
+#define GL_QUERY 0x82E3
+#endif
+#ifndef GL_PROGRAM_PIPELINE
+#define GL_PROGRAM_PIPELINE 0x82E4
+#endif
+#ifndef GL_SAMPLER
+#define GL_SAMPLER 0x82E6
+#endif
+#ifndef GL_DISPLAY_LIST
+#define GL_DISPLAY_LIST 0x82E7
+#endif
+#ifndef GL_MAX_LABEL_LENGTH
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#endif
+#ifndef GL_MAX_DEBUG_MESSAGE_LENGTH
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#endif
+#ifndef GL_MAX_DEBUG_LOGGED_MESSAGES
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#endif
+#ifndef GL_DEBUG_LOGGED_MESSAGES
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#endif
+#ifndef GL_DEBUG_SEVERITY_HIGH
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#endif
+#ifndef GL_DEBUG_SEVERITY_MEDIUM
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#endif
+#ifndef GL_DEBUG_SEVERITY_LOW
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#endif
+#ifndef GL_DEBUG_OUTPUT
+#define GL_DEBUG_OUTPUT 0x92E0
+#endif
+#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#endif
+#ifndef GL_STACK_OVERFLOW
+#define GL_STACK_OVERFLOW 0x0503
+#endif
+#ifndef GL_STACK_UNDERFLOW
+#define GL_STACK_UNDERFLOW 0x0504
+#endif
+
+typedef void (QOPENGLF_APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const GLvoid *userParam);
+
+#endif /* USE_MANUAL_DEFS */
+
+
+/*!
+ \internal
+*/
+static QOpenGLDebugMessage::Source qt_messageSourceFromGL(GLenum source)
+{
+ switch (source) {
+ case GL_DEBUG_SOURCE_API:
+ return QOpenGLDebugMessage::APISource;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
+ return QOpenGLDebugMessage::WindowSystemSource;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER:
+ return QOpenGLDebugMessage::ShaderCompilerSource;
+ case GL_DEBUG_SOURCE_THIRD_PARTY:
+ return QOpenGLDebugMessage::ThirdPartySource;
+ case GL_DEBUG_SOURCE_APPLICATION:
+ return QOpenGLDebugMessage::ApplicationSource;
+ case GL_DEBUG_SOURCE_OTHER:
+ return QOpenGLDebugMessage::OtherSource;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source from GL");
+ return QOpenGLDebugMessage::OtherSource;
+}
+
+/*!
+ \internal
+*/
+static GLenum qt_messageSourceToGL(QOpenGLDebugMessage::Source source)
+{
+ switch (source) {
+ case QOpenGLDebugMessage::InvalidSource:
+ break;
+ case QOpenGLDebugMessage::APISource:
+ return GL_DEBUG_SOURCE_API;
+ case QOpenGLDebugMessage::WindowSystemSource:
+ return GL_DEBUG_SOURCE_WINDOW_SYSTEM;
+ case QOpenGLDebugMessage::ShaderCompilerSource:
+ return GL_DEBUG_SOURCE_SHADER_COMPILER;
+ case QOpenGLDebugMessage::ThirdPartySource:
+ return GL_DEBUG_SOURCE_THIRD_PARTY;
+ case QOpenGLDebugMessage::ApplicationSource:
+ return GL_DEBUG_SOURCE_APPLICATION;
+ case QOpenGLDebugMessage::OtherSource:
+ return GL_DEBUG_SOURCE_OTHER;
+ case QOpenGLDebugMessage::AnySource:
+ break;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message source");
+ return GL_DEBUG_SOURCE_OTHER;
+}
+
+/*!
+ \internal
+*/
+static QString qt_messageSourceToString(QOpenGLDebugMessage::Source source)
+{
+ switch (source) {
+ case QOpenGLDebugMessage::InvalidSource:
+ return QStringLiteral("InvalidSource");
+ case QOpenGLDebugMessage::APISource:
+ return QStringLiteral("APISource");
+ case QOpenGLDebugMessage::WindowSystemSource:
+ return QStringLiteral("WindowSystemSource");
+ case QOpenGLDebugMessage::ShaderCompilerSource:
+ return QStringLiteral("ShaderCompilerSource");
+ case QOpenGLDebugMessage::ThirdPartySource:
+ return QStringLiteral("ThirdPartySource");
+ case QOpenGLDebugMessage::ApplicationSource:
+ return QStringLiteral("ApplicationSource");
+ case QOpenGLDebugMessage::OtherSource:
+ return QStringLiteral("OtherSource");
+ case QOpenGLDebugMessage::AnySource:
+ return QStringLiteral("AnySource");
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message source");
+ return QString();
+}
+
+/*!
+ \internal
+*/
+static QOpenGLDebugMessage::Type qt_messageTypeFromGL(GLenum type)
+{
+ switch (type) {
+ case GL_DEBUG_TYPE_ERROR:
+ return QOpenGLDebugMessage::ErrorType;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
+ return QOpenGLDebugMessage::DeprecatedBehaviorType;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
+ return QOpenGLDebugMessage::UndefinedBehaviorType;
+ case GL_DEBUG_TYPE_PORTABILITY:
+ return QOpenGLDebugMessage::PortabilityType;
+ case GL_DEBUG_TYPE_PERFORMANCE:
+ return QOpenGLDebugMessage::PerformanceType;
+ case GL_DEBUG_TYPE_OTHER:
+ return QOpenGLDebugMessage::OtherType;
+ case GL_DEBUG_TYPE_MARKER:
+ return QOpenGLDebugMessage::MarkerType;
+ case GL_DEBUG_TYPE_PUSH_GROUP:
+ return QOpenGLDebugMessage::GroupPushType;
+ case GL_DEBUG_TYPE_POP_GROUP:
+ return QOpenGLDebugMessage::GroupPopType;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type from GL");
+ return QOpenGLDebugMessage::OtherType;
+}
+
+/*!
+ \internal
+*/
+static GLenum qt_messageTypeToGL(QOpenGLDebugMessage::Type type)
+{
+ switch (type) {
+ case QOpenGLDebugMessage::InvalidType:
+ break;
+ case QOpenGLDebugMessage::ErrorType:
+ return GL_DEBUG_TYPE_ERROR;
+ case QOpenGLDebugMessage::DeprecatedBehaviorType:
+ return GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR;
+ case QOpenGLDebugMessage::UndefinedBehaviorType:
+ return GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR;
+ case QOpenGLDebugMessage::PortabilityType:
+ return GL_DEBUG_TYPE_PORTABILITY;
+ case QOpenGLDebugMessage::PerformanceType:
+ return GL_DEBUG_TYPE_PERFORMANCE;
+ case QOpenGLDebugMessage::OtherType:
+ return GL_DEBUG_TYPE_OTHER;
+ case QOpenGLDebugMessage::MarkerType:
+ return GL_DEBUG_TYPE_MARKER;
+ case QOpenGLDebugMessage::GroupPushType:
+ return GL_DEBUG_TYPE_PUSH_GROUP;
+ case QOpenGLDebugMessage::GroupPopType:
+ return GL_DEBUG_TYPE_POP_GROUP;
+ case QOpenGLDebugMessage::AnyType:
+ break;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type");
+ return GL_DEBUG_TYPE_OTHER;
+}
+
+/*!
+ \internal
+*/
+static QString qt_messageTypeToString(QOpenGLDebugMessage::Type type)
+{
+ switch (type) {
+ case QOpenGLDebugMessage::InvalidType:
+ return QStringLiteral("InvalidType");
+ case QOpenGLDebugMessage::ErrorType:
+ return QStringLiteral("ErrorType");
+ case QOpenGLDebugMessage::DeprecatedBehaviorType:
+ return QStringLiteral("DeprecatedBehaviorType");
+ case QOpenGLDebugMessage::UndefinedBehaviorType:
+ return QStringLiteral("UndefinedBehaviorType");
+ case QOpenGLDebugMessage::PortabilityType:
+ return QStringLiteral("PortabilityType");
+ case QOpenGLDebugMessage::PerformanceType:
+ return QStringLiteral("PerformanceType");
+ case QOpenGLDebugMessage::OtherType:
+ return QStringLiteral("OtherType");
+ case QOpenGLDebugMessage::MarkerType:
+ return QStringLiteral("MarkerType");
+ case QOpenGLDebugMessage::GroupPushType:
+ return QStringLiteral("GroupPushType");
+ case QOpenGLDebugMessage::GroupPopType:
+ return QStringLiteral("GroupPopType");
+ case QOpenGLDebugMessage::AnyType:
+ return QStringLiteral("AnyType");
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message type");
+ return QString();
+}
+
+/*!
+ \internal
+*/
+static QOpenGLDebugMessage::Severity qt_messageSeverityFromGL(GLenum severity)
+{
+ switch (severity) {
+ case GL_DEBUG_SEVERITY_HIGH:
+ return QOpenGLDebugMessage::HighSeverity;
+ case GL_DEBUG_SEVERITY_MEDIUM:
+ return QOpenGLDebugMessage::MediumSeverity;
+ case GL_DEBUG_SEVERITY_LOW:
+ return QOpenGLDebugMessage::LowSeverity;
+ case GL_DEBUG_SEVERITY_NOTIFICATION:
+ return QOpenGLDebugMessage::NotificationSeverity;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity from GL");
+ return QOpenGLDebugMessage::NotificationSeverity;
+}
+
+/*!
+ \internal
+*/
+static GLenum qt_messageSeverityToGL(QOpenGLDebugMessage::Severity severity)
+{
+ switch (severity) {
+ case QOpenGLDebugMessage::InvalidSeverity:
+ break;
+ case QOpenGLDebugMessage::HighSeverity:
+ return GL_DEBUG_SEVERITY_HIGH;
+ case QOpenGLDebugMessage::MediumSeverity:
+ return GL_DEBUG_SEVERITY_MEDIUM;
+ case QOpenGLDebugMessage::LowSeverity:
+ return GL_DEBUG_SEVERITY_LOW;
+ case QOpenGLDebugMessage::NotificationSeverity:
+ return GL_DEBUG_SEVERITY_NOTIFICATION;
+ case QOpenGLDebugMessage::AnySeverity:
+ break;
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message severity");
+ return GL_DEBUG_SEVERITY_NOTIFICATION;
+}
+
+/*!
+ \internal
+*/
+static QString qt_messageSeverityToString(QOpenGLDebugMessage::Severity severity)
+{
+ switch (severity) {
+ case QOpenGLDebugMessage::InvalidSeverity:
+ return QStringLiteral("InvalidSeverity");
+ case QOpenGLDebugMessage::HighSeverity:
+ return QStringLiteral("HighSeverity");
+ case QOpenGLDebugMessage::MediumSeverity:
+ return QStringLiteral("MediumSeverity");
+ case QOpenGLDebugMessage::LowSeverity:
+ return QStringLiteral("LowSeverity");
+ case QOpenGLDebugMessage::NotificationSeverity:
+ return QStringLiteral("NotificationSeverity");
+ case QOpenGLDebugMessage::AnySeverity:
+ return QStringLiteral("AnySeverity");
+ }
+
+ Q_ASSERT_X(false, Q_FUNC_INFO, "Unknown message severity");
+ return QString();
+}
+
+class QOpenGLDebugMessagePrivate : public QSharedData
+{
+public:
+ QOpenGLDebugMessagePrivate();
+
+ QString message;
+ GLuint id;
+ QOpenGLDebugMessage::Source source;
+ QOpenGLDebugMessage::Type type;
+ QOpenGLDebugMessage::Severity severity;
+};
+
+/*!
+ \internal
+*/
+QOpenGLDebugMessagePrivate::QOpenGLDebugMessagePrivate()
+ : message(),
+ id(0),
+ source(QOpenGLDebugMessage::InvalidSource),
+ type(QOpenGLDebugMessage::InvalidType),
+ severity(QOpenGLDebugMessage::InvalidSeverity)
+{
+}
+
+
+/*!
+ Constructs a debug message with an empty message string, id set to 0,
+ source set to InvalidSource, type set to InvalidType, and severity set to
+ InvalidSeverity.
+
+ \note This constructor should not be used to create a debug message;
+ instead, use the createApplicationMessage() or the createThirdPartyMessage()
+ static functions.
+
+ \sa createApplicationMessage(), createThirdPartyMessage()
+*/
+QOpenGLDebugMessage::QOpenGLDebugMessage()
+ : d(new QOpenGLDebugMessagePrivate)
+{
+}
+
+/*!
+ Constructs a debug message as a copy of \a debugMessage.
+
+ \sa operator=()
+*/
+QOpenGLDebugMessage::QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage)
+ : d(debugMessage.d)
+{
+}
+
+/*!
+ Destroys this debug message.
+*/
+QOpenGLDebugMessage::~QOpenGLDebugMessage()
+{
+}
+
+/*!
+ Assigns the message \a debugMessage to this object, and returns a reference
+ to the copy.
+*/
+QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(const QOpenGLDebugMessage &debugMessage)
+{
+ d = debugMessage.d;
+ return *this;
+}
+
+/*!
+ \fn QOpenGLDebugMessage &QOpenGLDebugMessage::operator=(QOpenGLDebugMessage &&debugMessage)
+
+ Move-assigns \a debugMessage to this object.
+*/
+
+/*!
+ \fn void QOpenGLDebugMessage::swap(QOpenGLDebugMessage &debugMessage)
+
+ Swaps the message \a debugMessage with this message. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ Returns the source of the debug message.
+*/
+QOpenGLDebugMessage::Source QOpenGLDebugMessage::source() const
+{
+ return d->source;
+}
+
+/*!
+ Returns the type of the debug message.
+*/
+QOpenGLDebugMessage::Type QOpenGLDebugMessage::type() const
+{
+ return d->type;
+}
+
+/*!
+ Returns the severity of the debug message.
+*/
+QOpenGLDebugMessage::Severity QOpenGLDebugMessage::severity() const
+{
+ return d->severity;
+}
+
+/*!
+ Returns the id of the debug message. Ids are generally vendor-specific.
+*/
+GLuint QOpenGLDebugMessage::id() const
+{
+ return d->id;
+}
+
+/*!
+ Returns the textual message contained by this debug message.
+*/
+QString QOpenGLDebugMessage::message() const
+{
+ return d->message;
+}
+
+/*!
+ Constructs and returns a debug message with \a text as its text, \a id
+ as id, \a severity as severity, and \a type as type. The message source
+ will be set to ApplicationSource.
+
+ \sa QOpenGLDebugLogger::logMessage(), createThirdPartyMessage()
+*/
+QOpenGLDebugMessage QOpenGLDebugMessage::createApplicationMessage(const QString &text,
+ GLuint id,
+ QOpenGLDebugMessage::Severity severity,
+ QOpenGLDebugMessage::Type type)
+{
+ QOpenGLDebugMessage m;
+ m.d->message = text;
+ m.d->id = id;
+ m.d->severity = severity;
+ m.d->type = type;
+ m.d->source = ApplicationSource;
+ return m;
+}
+
+/*!
+ Constructs and returns a debug message with \a text as its text, \a id
+ as id, \a severity as severity, and \a type as type. The message source
+ will be set to ThirdPartySource.
+
+ \sa QOpenGLDebugLogger::logMessage(), createApplicationMessage()
+*/
+QOpenGLDebugMessage QOpenGLDebugMessage::createThirdPartyMessage(const QString &text,
+ GLuint id,
+ QOpenGLDebugMessage::Severity severity,
+ QOpenGLDebugMessage::Type type)
+{
+ QOpenGLDebugMessage m;
+ m.d->message = text;
+ m.d->id = id;
+ m.d->severity = severity;
+ m.d->type = type;
+ m.d->source = ThirdPartySource;
+ return m;
+}
+
+/*!
+ Returns \c true if this debug message is equal to \a debugMessage, or false
+ otherwise. Two debugging messages are equal if they have the same textual
+ message, the same id, the same source, the same type and the same severity.
+
+ \sa operator!=()
+*/
+bool QOpenGLDebugMessage::operator==(const QOpenGLDebugMessage &debugMessage) const
+{
+ return (d == debugMessage.d)
+ || (d->id == debugMessage.d->id
+ && d->source == debugMessage.d->source
+ && d->type == debugMessage.d->type
+ && d->severity == debugMessage.d->severity
+ && d->message == debugMessage.d->message);
+}
+
+/*!
+ \fn bool QOpenGLDebugMessage::operator!=(const QOpenGLDebugMessage &debugMessage) const
+
+ Returns \c true if this message is different from \a debugMessage, or false
+ otherwise.
+
+ \sa operator==()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+/*!
+ \relates QOpenGLDebugMessage
+
+ Writes the source \a source into the debug object \a debug for debugging
+ purposes.
+*/
+QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "QOpenGLDebugMessage::Source("
+ << qt_messageSourceToString(source)
+ << ')';
+ return debug;
+}
+
+/*!
+ \relates QOpenGLDebugMessage
+
+ Writes the type \a type into the debug object \a debug for debugging
+ purposes.
+*/
+QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "QOpenGLDebugMessage::Type("
+ << qt_messageTypeToString(type)
+ << ')';
+ return debug;
+}
+
+/*!
+ \relates QOpenGLDebugMessage
+
+ Writes the severity \a severity into the debug object \a debug for debugging
+ purposes.
+*/
+QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "QOpenGLDebugMessage::Severity("
+ << qt_messageSeverityToString(severity)
+ << ')';
+ return debug;
+}
+
+/*!
+ \relates QOpenGLDebugMessage
+
+ Writes the message \a message into the debug object \a debug for debugging
+ purposes.
+*/
+QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace() << "QOpenGLDebugMessage("
+ << qt_messageSourceToString(message.source()) << ", "
+ << message.id() << ", "
+ << message.message() << ", "
+ << qt_messageSeverityToString(message.severity()) << ", "
+ << qt_messageTypeToString(message.type()) << ')';
+ return debug;
+
+}
+#endif // QT_NO_DEBUG_STREAM
+
+typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageControl_t)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageInsert_t)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+typedef void (QOPENGLF_APIENTRYP qt_glDebugMessageCallback_t)(GLDEBUGPROC callback, const void *userParam);
+typedef GLuint (QOPENGLF_APIENTRYP qt_glGetDebugMessageLog_t)(GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+typedef void (QOPENGLF_APIENTRYP qt_glPushDebugGroup_t)(GLenum source, GLuint id, GLsizei length, const GLchar *message);
+typedef void (QOPENGLF_APIENTRYP qt_glPopDebugGroup_t)();
+typedef void (QOPENGLF_APIENTRYP qt_glGetPointerv_t)(GLenum pname, GLvoid **params);
+
+class QOpenGLDebugLoggerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLDebugLogger)
+public:
+ QOpenGLDebugLoggerPrivate();
+
+ void handleMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *rawMessage);
+ void controlDebugMessages(QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types,
+ QOpenGLDebugMessage::Severities severities,
+ const QVector<GLuint> &ids,
+ const QByteArray &callerName,
+ bool enable);
+ void _q_contextAboutToBeDestroyed();
+
+ qt_glDebugMessageControl_t glDebugMessageControl;
+ qt_glDebugMessageInsert_t glDebugMessageInsert;
+ qt_glDebugMessageCallback_t glDebugMessageCallback;
+ qt_glGetDebugMessageLog_t glGetDebugMessageLog;
+ qt_glPushDebugGroup_t glPushDebugGroup;
+ qt_glPopDebugGroup_t glPopDebugGroup;
+ qt_glGetPointerv_t glGetPointerv;
+
+ GLDEBUGPROC oldDebugCallbackFunction;
+ void *oldDebugCallbackParameter;
+ QOpenGLContext *context;
+ GLint maxMessageLength;
+ QOpenGLDebugLogger::LoggingMode loggingMode;
+ bool initialized : 1;
+ bool isLogging : 1;
+ bool debugWasEnabled : 1;
+ bool syncDebugWasEnabled : 1;
+};
+
+/*!
+ \internal
+*/
+QOpenGLDebugLoggerPrivate::QOpenGLDebugLoggerPrivate()
+ : glDebugMessageControl(nullptr),
+ glDebugMessageInsert(nullptr),
+ glDebugMessageCallback(nullptr),
+ glGetDebugMessageLog(nullptr),
+ glPushDebugGroup(nullptr),
+ glPopDebugGroup(nullptr),
+ oldDebugCallbackFunction(nullptr),
+ context(nullptr),
+ maxMessageLength(0),
+ loggingMode(QOpenGLDebugLogger::AsynchronousLogging),
+ initialized(false),
+ isLogging(false),
+ debugWasEnabled(false),
+ syncDebugWasEnabled(false)
+{
+}
+
+/*!
+ \internal
+*/
+void QOpenGLDebugLoggerPrivate::handleMessage(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *rawMessage)
+{
+ if (oldDebugCallbackFunction)
+ oldDebugCallbackFunction(source, type, id, severity, length, rawMessage, oldDebugCallbackParameter);
+
+ QOpenGLDebugMessage message;
+
+ QOpenGLDebugMessagePrivate *messagePrivate = message.d.data();
+ messagePrivate->source = qt_messageSourceFromGL(source);
+ messagePrivate->type = qt_messageTypeFromGL(type);
+ messagePrivate->id = id;
+ messagePrivate->severity = qt_messageSeverityFromGL(severity);
+ // not passing the length to fromUtf8, as some bugged OpenGL drivers
+ // do not handle the length correctly. Just rely on the message to be NUL terminated.
+ messagePrivate->message = QString::fromUtf8(rawMessage);
+
+ Q_Q(QOpenGLDebugLogger);
+ emit q->messageLogged(message);
+}
+
+/*!
+ \internal
+*/
+void QOpenGLDebugLoggerPrivate::controlDebugMessages(QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types,
+ QOpenGLDebugMessage::Severities severities,
+ const QVector<GLuint> &ids,
+ const QByteArray &callerName,
+ bool enable)
+{
+ if (!initialized) {
+ qWarning("QOpenGLDebugLogger::%s(): object must be initialized before enabling/disabling messages", callerName.constData());
+ return;
+ }
+ if (sources == QOpenGLDebugMessage::InvalidSource) {
+ qWarning("QOpenGLDebugLogger::%s(): invalid source specified", callerName.constData());
+ return;
+ }
+ if (types == QOpenGLDebugMessage::InvalidType) {
+ qWarning("QOpenGLDebugLogger::%s(): invalid type specified", callerName.constData());
+ return;
+ }
+ if (severities == QOpenGLDebugMessage::InvalidSeverity) {
+ qWarning("QOpenGLDebugLogger::%s(): invalid severity specified", callerName.constData());
+ return;
+ }
+
+ QVarLengthArray<GLenum, 8> glSources;
+ QVarLengthArray<GLenum, 8> glTypes;
+ QVarLengthArray<GLenum, 8> glSeverities;
+
+ if (ids.count() > 0) {
+ Q_ASSERT(severities == QOpenGLDebugMessage::AnySeverity);
+
+ // The GL_KHR_debug extension says:
+ //
+ // - If <count> is greater than zero, then <ids> is an array of <count>
+ // message IDs for the specified combination of <source> and <type>. In
+ // this case, if <source> or <type> is DONT_CARE, or <severity> is not
+ // DONT_CARE, the error INVALID_OPERATION is generated. If <count> is
+ // zero, the value if <ids> is ignored.
+ //
+ // This means we can't convert AnySource or AnyType into DONT_CARE, but we have to roll
+ // them into individual sources/types.
+
+ if (sources == QOpenGLDebugMessage::AnySource) {
+ sources = QOpenGLDebugMessage::InvalidSource;
+ for (uint i = 1; i <= QOpenGLDebugMessage::LastSource; i = i << 1)
+ sources |= QOpenGLDebugMessage::Source(i);
+ }
+
+ if (types == QOpenGLDebugMessage::AnyType) {
+ types = QOpenGLDebugMessage::InvalidType;
+ for (uint i = 1; i <= QOpenGLDebugMessage::LastType; i = i << 1)
+ types |= QOpenGLDebugMessage::Type(i);
+ }
+ }
+
+#define CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(type, source, target) \
+ if (source == QOpenGLDebugMessage::Any ## type) { \
+ target << GL_DONT_CARE; \
+ } else { \
+ for (uint i = 1; i <= QOpenGLDebugMessage::Last ## type; i = i << 1) \
+ if (source.testFlag(QOpenGLDebugMessage:: type (i))) \
+ target << qt_message ## type ## ToGL (QOpenGLDebugMessage:: type (i)); \
+ }
+
+ CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Source, sources, glSources)
+ CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Type, types, glTypes)
+ CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS(Severity, severities, glSeverities)
+#undef CONVERT_TO_GL_DEBUG_MESSAGE_CONTROL_PARAMETERS
+
+ const GLsizei idCount = ids.count();
+ // The GL_KHR_debug extension says that if idCount is 0, idPtr must be ignored.
+ // Unfortunately, some bugged drivers do NOT ignore it, so pass NULL in case.
+ const GLuint * const idPtr = idCount ? ids.constData() : nullptr;
+
+ for (GLenum source : glSources)
+ for (GLenum type : glTypes)
+ for (GLenum severity : glSeverities)
+ glDebugMessageControl(source, type, severity, idCount, idPtr, GLboolean(enable));
+}
+
+/*!
+ \internal
+*/
+void QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed()
+{
+ Q_ASSERT(context);
+
+ // Re-make our context current somehow, otherwise stopLogging will fail.
+
+ // Save the current context and its surface in case we need to set them back
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ QSurface *currentSurface = nullptr;
+
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+
+ if (context != currentContext) {
+ // Make our old context current on a temporary surface
+ if (currentContext)
+ currentSurface = currentContext->surface();
+
+ offscreenSurface.reset(new QOffscreenSurface);
+ offscreenSurface->setFormat(context->format());
+ offscreenSurface->create();
+ if (!context->makeCurrent(offscreenSurface.data()))
+ qWarning("QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed(): could not make the owning GL context current for cleanup");
+ }
+
+ Q_Q(QOpenGLDebugLogger);
+ q->stopLogging();
+
+ if (offscreenSurface) {
+ // We did change the current context: set it back
+ if (currentContext)
+ currentContext->makeCurrent(currentSurface);
+ else
+ context->doneCurrent();
+ }
+
+ QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed()));
+ context = nullptr;
+ initialized = false;
+}
+
+extern "C" {
+static void QOPENGLF_APIENTRY qt_opengl_debug_callback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *rawMessage,
+ const GLvoid *userParam)
+{
+ QOpenGLDebugLoggerPrivate *loggerPrivate = static_cast<QOpenGLDebugLoggerPrivate *>(const_cast<GLvoid *>(userParam));
+ loggerPrivate->handleMessage(source, type, id, severity, length, rawMessage);
+}
+}
+
+/*!
+ Constructs a new logger object with the given \a parent.
+
+ \note The object must be initialized before logging can happen.
+
+ \sa initialize()
+*/
+QOpenGLDebugLogger::QOpenGLDebugLogger(QObject *parent)
+ : QObject(*new QOpenGLDebugLoggerPrivate, parent)
+{
+ // QOpenGLDebugMessage is going to be mostly used as an argument
+ // of a cross thread connection, therefore let's ease the life for the users
+ // and register the type for them.
+ qRegisterMetaType<QOpenGLDebugMessage>();
+}
+
+/*!
+ Destroys the logger object.
+*/
+QOpenGLDebugLogger::~QOpenGLDebugLogger()
+{
+ stopLogging();
+}
+
+/*!
+ Initializes the object in the current OpenGL context. The context must
+ support the \c{GL_KHR_debug} extension for the initialization to succeed.
+ The object must be initialized before any logging can happen.
+
+ It is safe to call this function multiple times from the same context.
+
+ This function can also be used to change the context of a previously
+ initialized object; note that in this case the object must not be logging
+ when you call this function.
+
+ Returns \c true if the logger is successfully initialized; false otherwise.
+
+ \sa QOpenGLContext
+*/
+bool QOpenGLDebugLogger::initialize()
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (!context) {
+ qWarning("QOpenGLDebugLogger::initialize(): no current OpenGL context found.");
+ return false;
+ }
+
+ Q_D(QOpenGLDebugLogger);
+ if (d->context == context) {
+ // context is non-NULL, d->context is non NULL only on successful initialization.
+ Q_ASSERT(d->initialized);
+ return true;
+ }
+
+ if (d->isLogging) {
+ qWarning("QOpenGLDebugLogger::initialize(): cannot initialize the object while logging. Please stop the logging first.");
+ return false;
+ }
+
+ if (d->context)
+ disconnect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed()));
+
+ d->initialized = false;
+ d->context = nullptr;
+
+ if (!context->hasExtension(QByteArrayLiteral("GL_KHR_debug")))
+ return false;
+
+ d->context = context;
+ connect(d->context, SIGNAL(aboutToBeDestroyed()), this, SLOT(_q_contextAboutToBeDestroyed()));
+
+#define GET_DEBUG_PROC_ADDRESS(procName) \
+ d->procName = reinterpret_cast< qt_ ## procName ## _t >( \
+ d->context->getProcAddress(d->context->isOpenGLES() ? (#procName "KHR") : (#procName)) \
+ );
+
+ GET_DEBUG_PROC_ADDRESS(glDebugMessageControl);
+ GET_DEBUG_PROC_ADDRESS(glDebugMessageInsert);
+ GET_DEBUG_PROC_ADDRESS(glDebugMessageCallback);
+ GET_DEBUG_PROC_ADDRESS(glGetDebugMessageLog);
+ GET_DEBUG_PROC_ADDRESS(glPushDebugGroup);
+ GET_DEBUG_PROC_ADDRESS(glPopDebugGroup);
+ GET_DEBUG_PROC_ADDRESS(glGetPointerv)
+
+#undef GET_DEBUG_PROC_ADDRESS
+
+ QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_DEBUG_MESSAGE_LENGTH, &d->maxMessageLength);
+
+#ifndef QT_NO_DEBUG
+ if (!d->context->format().testOption(QSurfaceFormat::DebugContext)) {
+ qWarning("QOpenGLDebugLogger::initialize(): the current context is not a debug context:\n"
+ " this means that the GL may not generate any debug output at all.\n"
+ " To avoid this warning, try creating the context with the\n"
+ " QSurfaceFormat::DebugContext surface format option.");
+ }
+#endif // QT_NO_DEBUG
+
+ d->initialized = true;
+ return true;
+}
+
+/*!
+ Returns \c true if this object is currently logging, false otherwise.
+
+ \sa startLogging()
+*/
+bool QOpenGLDebugLogger::isLogging() const
+{
+ Q_D(const QOpenGLDebugLogger);
+ return d->isLogging;
+}
+
+/*!
+ Starts logging messages coming from the OpenGL server. When a new message
+ is received, the signal messageLogged() is emitted, carrying the logged
+ message as argument.
+
+ \a loggingMode specifies whether the logging must be asynchronous (the default)
+ or synchronous.
+
+ QOpenGLDebugLogger will record the values of \c{GL_DEBUG_OUTPUT} and
+ \c{GL_DEBUG_OUTPUT_SYNCHRONOUS} when logging is started, and set them back
+ when logging is stopped. Moreover, any user-defined OpenGL debug callback
+ installed when this function is invoked will be restored when logging is
+ stopped; QOpenGLDebugLogger will ensure that the pre-existing callback will
+ still be invoked when logging.
+
+ \note It's not possible to change the logging mode without stopping and
+ starting logging again. This might change in a future version of Qt.
+
+ \note The object must be initialized before logging can happen.
+
+ \sa stopLogging(), initialize()
+*/
+void QOpenGLDebugLogger::startLogging(QOpenGLDebugLogger::LoggingMode loggingMode)
+{
+ Q_D(QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::startLogging(): object must be initialized before logging can start");
+ return;
+ }
+ if (d->isLogging) {
+ qWarning("QOpenGLDebugLogger::startLogging(): this object is already logging");
+ return;
+ }
+
+ d->isLogging = true;
+ d->loggingMode = loggingMode;
+
+ d->glGetPointerv(GL_DEBUG_CALLBACK_FUNCTION, reinterpret_cast<void **>(&d->oldDebugCallbackFunction));
+ d->glGetPointerv(GL_DEBUG_CALLBACK_USER_PARAM, &d->oldDebugCallbackParameter);
+
+ d->glDebugMessageCallback(&qt_opengl_debug_callback, d);
+
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ d->debugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT);
+ d->syncDebugWasEnabled = funcs->glIsEnabled(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+ if (d->loggingMode == SynchronousLogging)
+ funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ else
+ funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+
+ funcs->glEnable(GL_DEBUG_OUTPUT);
+}
+
+/*!
+ Returns the logging mode of the object.
+
+ \sa startLogging()
+*/
+QOpenGLDebugLogger::LoggingMode QOpenGLDebugLogger::loggingMode() const
+{
+ Q_D(const QOpenGLDebugLogger);
+ return d->loggingMode;
+}
+
+/*!
+ Stops logging messages from the OpenGL server.
+
+ \sa startLogging()
+*/
+void QOpenGLDebugLogger::stopLogging()
+{
+ Q_D(QOpenGLDebugLogger);
+ if (!d->isLogging)
+ return;
+
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext || currentContext != d->context) {
+ qWarning("QOpenGLDebugLogger::stopLogging(): attempting to stop logging with the wrong OpenGL context current");
+ return;
+ }
+
+ d->isLogging = false;
+
+ d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter);
+
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ if (!d->debugWasEnabled)
+ funcs->glDisable(GL_DEBUG_OUTPUT);
+
+ if (d->syncDebugWasEnabled)
+ funcs->glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+ else
+ funcs->glDisable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
+}
+
+/*!
+ Inserts the message \a debugMessage into the OpenGL debug log. This provides
+ a way for applications or libraries to insert custom messages that can
+ ease the debugging of OpenGL applications.
+
+ \note \a debugMessage must have QOpenGLDebugMessage::ApplicationSource or
+ QOpenGLDebugMessage::ThirdPartySource as its source, and a valid
+ type and severity, otherwise it will not be inserted into the log.
+
+ \note The object must be initialized before logging can happen.
+
+ \sa initialize()
+*/
+void QOpenGLDebugLogger::logMessage(const QOpenGLDebugMessage &debugMessage)
+{
+ Q_D(QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::logMessage(): object must be initialized before logging messages");
+ return;
+ }
+ if (debugMessage.source() != QOpenGLDebugMessage::ApplicationSource
+ && debugMessage.source() != QOpenGLDebugMessage::ThirdPartySource) {
+ qWarning("QOpenGLDebugLogger::logMessage(): using a message source different from ApplicationSource\n"
+ " or ThirdPartySource is not supported by GL_KHR_debug. The message will not be logged.");
+ return;
+ }
+ if (debugMessage.type() == QOpenGLDebugMessage::InvalidType
+ || debugMessage.type() == QOpenGLDebugMessage::AnyType
+ || debugMessage.severity() == QOpenGLDebugMessage::InvalidSeverity
+ || debugMessage.severity() == QOpenGLDebugMessage::AnySeverity) {
+ qWarning("QOpenGLDebugLogger::logMessage(): the message has a non-valid type and/or severity. The message will not be logged.");
+ return;
+ }
+
+ const GLenum source = qt_messageSourceToGL(debugMessage.source());
+ const GLenum type = qt_messageTypeToGL(debugMessage.type());
+ const GLenum severity = qt_messageSeverityToGL(debugMessage.severity());
+ QByteArray rawMessage = debugMessage.message().toUtf8();
+ rawMessage.append('\0');
+
+ if (rawMessage.length() > d->maxMessageLength) {
+ qWarning("QOpenGLDebugLogger::logMessage(): message too long, truncating it\n"
+ " (%d bytes long, but the GL accepts up to %d bytes)", rawMessage.length(), d->maxMessageLength);
+ rawMessage.resize(d->maxMessageLength - 1);
+ rawMessage.append('\0');
+ }
+
+ // Don't pass rawMessage.length(), as unfortunately bugged
+ // OpenGL drivers will eat the trailing NUL in the message. Just rely
+ // on the message being NUL terminated.
+ d->glDebugMessageInsert(source,
+ type,
+ debugMessage.id(),
+ severity,
+ -1,
+ rawMessage.constData());
+}
+
+/*!
+ Pushes a debug group with name \a name, id \a id, and source \a source onto
+ the debug groups stack. If the group is successfully pushed, OpenGL will
+ automatically log a message with message \a name, id \a id, source \a
+ source, type QOpenGLDebugMessage::GroupPushType and severity
+ QOpenGLDebugMessage::NotificationSeverity.
+
+ The newly pushed group will inherit the same filtering settings of the
+ group that was on the top of the stack; that is, the filtering will not be
+ changed by pushing a new group.
+
+ \note The \a source must either be QOpenGLDebugMessage::ApplicationSource or
+ QOpenGLDebugMessage::ThirdPartySource, otherwise the group will not be pushed.
+
+ \note The object must be initialized before managing debug groups.
+
+ \sa popGroup(), enableMessages(), disableMessages()
+*/
+void QOpenGLDebugLogger::pushGroup(const QString &name, GLuint id, QOpenGLDebugMessage::Source source)
+{
+ Q_D(QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before pushing a debug group");
+ return;
+ }
+ if (source != QOpenGLDebugMessage::ApplicationSource
+ && source != QOpenGLDebugMessage::ThirdPartySource) {
+ qWarning("QOpenGLDebugLogger::pushGroup(): using a source different from ApplicationSource\n"
+ " or ThirdPartySource is not supported by GL_KHR_debug. The group will not be pushed.");
+ return;
+ }
+
+ QByteArray rawName = name.toUtf8();
+ rawName.append('\0');
+ if (rawName.length() > d->maxMessageLength) {
+ qWarning("QOpenGLDebugLogger::pushGroup(): group name too long, truncating it\n"
+ " (%d bytes long, but the GL accepts up to %d bytes)", rawName.length(), d->maxMessageLength);
+ rawName.resize(d->maxMessageLength - 1);
+ rawName.append('\0');
+ }
+
+ // Don't pass rawMessage.length(), as unfortunately bugged
+ // OpenGL drivers will eat the trailing NUL in the name. Just rely
+ // on the name being NUL terminated.
+ d->glPushDebugGroup(qt_messageSourceToGL(source), id, -1, rawName.constData());
+}
+
+/*!
+ Pops the topmost debug group from the debug groups stack. If the group is
+ successfully popped, OpenGL will automatically log a message with message,
+ id and source matching those of the popped group, type
+ QOpenGLDebugMessage::GroupPopType and severity
+ QOpenGLDebugMessage::NotificationSeverity.
+
+ Popping a debug group will restore the message filtering settings of the
+ group that becomes the top of the debug groups stack.
+
+ \note The object must be initialized before managing debug groups.
+
+ \sa pushGroup()
+*/
+void QOpenGLDebugLogger::popGroup()
+{
+ Q_D(QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::pushGroup(): object must be initialized before popping a debug group");
+ return;
+ }
+
+ d->glPopDebugGroup();
+}
+
+/*!
+ Enables the logging of messages from the given \a sources, of the given \a
+ types and with the given \a severities and any message id.
+
+ The logging will be enabled in the current control group.
+
+ \sa disableMessages(), pushGroup(), popGroup()
+*/
+void QOpenGLDebugLogger::enableMessages(QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types,
+ QOpenGLDebugMessage::Severities severities)
+{
+ Q_D(QOpenGLDebugLogger);
+ d->controlDebugMessages(sources,
+ types,
+ severities,
+ QVector<GLuint>(),
+ QByteArrayLiteral("enableMessages"),
+ true);
+}
+
+/*!
+ Enables the logging of messages with the given \a ids, from the given \a
+ sources and of the given \a types and any severity.
+
+ The logging will be enabled in the current control group.
+
+ \sa disableMessages(), pushGroup(), popGroup()
+*/
+void QOpenGLDebugLogger::enableMessages(const QVector<GLuint> &ids,
+ QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types)
+{
+ Q_D(QOpenGLDebugLogger);
+ d->controlDebugMessages(sources,
+ types,
+ QOpenGLDebugMessage::AnySeverity,
+ ids,
+ QByteArrayLiteral("enableMessages"),
+ true);
+}
+
+/*!
+ Disables the logging of messages with the given \a sources, of the given \a
+ types and with the given \a severities and any message id.
+
+ The logging will be disabled in the current control group.
+
+ \sa enableMessages(), pushGroup(), popGroup()
+*/
+void QOpenGLDebugLogger::disableMessages(QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types,
+ QOpenGLDebugMessage::Severities severities)
+{
+ Q_D(QOpenGLDebugLogger);
+ d->controlDebugMessages(sources,
+ types,
+ severities,
+ QVector<GLuint>(),
+ QByteArrayLiteral("disableMessages"),
+ false);
+}
+
+/*!
+ Disables the logging of messages with the given \a ids, from the given \a
+ sources and of the given \a types and any severity.
+
+ The logging will be disabled in the current control group.
+
+ \sa enableMessages(), pushGroup(), popGroup()
+*/
+void QOpenGLDebugLogger::disableMessages(const QVector<GLuint> &ids,
+ QOpenGLDebugMessage::Sources sources,
+ QOpenGLDebugMessage::Types types)
+{
+ Q_D(QOpenGLDebugLogger);
+ d->controlDebugMessages(sources,
+ types,
+ QOpenGLDebugMessage::AnySeverity,
+ ids,
+ QByteArrayLiteral("disableMessages"),
+ false);
+}
+
+/*!
+ Reads all the available messages in the OpenGL internal debug log and
+ returns them. Moreover, this function will clear the internal debug log,
+ so that subsequent invocations will not return messages that were
+ already returned.
+
+ \sa startLogging()
+*/
+QList<QOpenGLDebugMessage> QOpenGLDebugLogger::loggedMessages() const
+{
+ Q_D(const QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::loggedMessages(): object must be initialized before reading logged messages");
+ return QList<QOpenGLDebugMessage>();
+ }
+
+ static const GLuint maxMessageCount = 128;
+ GLuint messagesRead;
+ GLenum messageSources[maxMessageCount];
+ GLenum messageTypes[maxMessageCount];
+ GLuint messageIds[maxMessageCount];
+ GLenum messageSeverities[maxMessageCount];
+ GLsizei messageLengths[maxMessageCount];
+
+ QByteArray messagesBuffer;
+ messagesBuffer.resize(maxMessageCount * d->maxMessageLength);
+
+ QList<QOpenGLDebugMessage> messages;
+ do {
+ messagesRead = d->glGetDebugMessageLog(maxMessageCount,
+ GLsizei(messagesBuffer.size()),
+ messageSources,
+ messageTypes,
+ messageIds,
+ messageSeverities,
+ messageLengths,
+ messagesBuffer.data());
+
+ const char *messagesBufferPtr = messagesBuffer.constData();
+ for (GLuint i = 0; i < messagesRead; ++i) {
+ QOpenGLDebugMessage message;
+
+ QOpenGLDebugMessagePrivate *messagePrivate = message.d.data();
+ messagePrivate->source = qt_messageSourceFromGL(messageSources[i]);
+ messagePrivate->type = qt_messageTypeFromGL(messageTypes[i]);
+ messagePrivate->id = messageIds[i];
+ messagePrivate->severity = qt_messageSeverityFromGL(messageSeverities[i]);
+ messagePrivate->message = QString::fromUtf8(messagesBufferPtr, messageLengths[i] - 1);
+
+ messagesBufferPtr += messageLengths[i];
+ messages << message;
+ }
+ } while (messagesRead == maxMessageCount);
+
+ return messages;
+}
+
+/*!
+ \fn void QOpenGLDebugLogger::messageLogged(const QOpenGLDebugMessage &debugMessage)
+
+ This signal is emitted when a debug message (wrapped by the \a debugMessage
+ argument) is logged from the OpenGL server.
+
+ Depending on the OpenGL implementation, this signal can be emitted
+ from other threads than the one(s) the receiver(s) lives in, and even
+ different from the thread the QOpenGLContext in which this object has
+ been initialized lives in. Moreover, the signal could be emitted from
+ multiple threads at the same time. This is normally not a problem,
+ as Qt will utilize a queued connection for cross-thread signal emissions,
+ but if you force the connection type to Direct then you must be aware of
+ the potential races in the slots connected to this signal.
+
+ If logging have been started in SynchronousLogging mode, OpenGL guarantees
+ that this signal will be emitted from the same thread the QOpenGLContext
+ has been bound to, and no concurrent invocations will ever happen.
+
+ \note Logging must have been started, or this signal will not be emitted.
+
+ \sa startLogging()
+*/
+
+/*!
+ Returns the maximum supported length, in bytes, for the text of the messages
+ passed to logMessage(). This is also the maximum length of a debug group
+ name, as pushing or popping groups will automatically log a message with
+ the debug group name as the message text.
+
+ If a message text is too long, it will be automatically truncated by
+ QOpenGLDebugLogger.
+
+ \note Message texts are encoded in UTF-8 when they get passed to OpenGL, so
+ their size in bytes does not usually match the amount of UTF-16 code units,
+ as returned, for instance, by QString::length(). (It does if the message contains
+ 7-bit ASCII only data, which is typical for debug messages.)
+*/
+qint64 QOpenGLDebugLogger::maximumMessageLength() const
+{
+ Q_D(const QOpenGLDebugLogger);
+ if (!d->initialized) {
+ qWarning("QOpenGLDebugLogger::maximumMessageLength(): object must be initialized before reading the maximum message length");
+ return -1;
+ }
+ return d->maxMessageLength;
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qopengldebug.cpp"
diff --git a/src/opengl/qopengldebug.h b/src/opengl/qopengldebug.h
new file mode 100644
index 0000000000..fef2782302
--- /dev/null
+++ b/src/opengl/qopengldebug.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the 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 QOPENGLDEBUG_H
+#define QOPENGLDEBUG_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#ifndef QT_NO_OPENGL
+
+#include <QtCore/qshareddata.h>
+#include <QtCore/qflags.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qdebug.h>
+#include <QtGui/qopenglcontext.h>
+
+#if defined(Q_CLANG_QDOC)
+#undef GLuint
+typedef unsigned int GLuint;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLDebugLogger;
+class QOpenGLDebugLoggerPrivate;
+class QOpenGLDebugMessagePrivate;
+
+class Q_OPENGL_EXPORT QOpenGLDebugMessage
+{
+public:
+ enum Source {
+ InvalidSource = 0x00000000,
+ APISource = 0x00000001,
+ WindowSystemSource = 0x00000002,
+ ShaderCompilerSource = 0x00000004,
+ ThirdPartySource = 0x00000008,
+ ApplicationSource = 0x00000010,
+ OtherSource = 0x00000020,
+ LastSource = OtherSource, // private API
+ AnySource = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(Sources, Source)
+
+ enum Type {
+ InvalidType = 0x00000000,
+ ErrorType = 0x00000001,
+ DeprecatedBehaviorType = 0x00000002,
+ UndefinedBehaviorType = 0x00000004,
+ PortabilityType = 0x00000008,
+ PerformanceType = 0x00000010,
+ OtherType = 0x00000020,
+ MarkerType = 0x00000040,
+ GroupPushType = 0x00000080,
+ GroupPopType = 0x00000100,
+ LastType = GroupPopType, // private API
+ AnyType = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(Types, Type)
+
+ enum Severity {
+ InvalidSeverity = 0x00000000,
+ HighSeverity = 0x00000001,
+ MediumSeverity = 0x00000002,
+ LowSeverity = 0x00000004,
+ NotificationSeverity = 0x00000008,
+ LastSeverity = NotificationSeverity, // private API
+ AnySeverity = 0xffffffff
+ };
+ Q_DECLARE_FLAGS(Severities, Severity)
+
+ QOpenGLDebugMessage();
+ QOpenGLDebugMessage(const QOpenGLDebugMessage &debugMessage);
+
+ QOpenGLDebugMessage &operator=(const QOpenGLDebugMessage &debugMessage);
+ QOpenGLDebugMessage &operator=(QOpenGLDebugMessage &&other) noexcept { swap(other); return *this; }
+ ~QOpenGLDebugMessage();
+
+ void swap(QOpenGLDebugMessage &other) noexcept { qSwap(d, other.d); }
+
+ Source source() const;
+ Type type() const;
+ Severity severity() const;
+ GLuint id() const;
+ QString message() const;
+
+ static QOpenGLDebugMessage createApplicationMessage(const QString &text,
+ GLuint id = 0,
+ Severity severity = NotificationSeverity,
+ Type type = OtherType);
+ static QOpenGLDebugMessage createThirdPartyMessage(const QString &text,
+ GLuint id = 0,
+ Severity severity = NotificationSeverity,
+ Type type = OtherType);
+
+ bool operator==(const QOpenGLDebugMessage &debugMessage) const;
+ inline bool operator!=(const QOpenGLDebugMessage &debugMessage) const { return !operator==(debugMessage); }
+
+private:
+ friend class QOpenGLDebugLogger;
+ friend class QOpenGLDebugLoggerPrivate;
+ QSharedDataPointer<QOpenGLDebugMessagePrivate> d;
+};
+
+Q_DECLARE_SHARED(QOpenGLDebugMessage)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Sources)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Types)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLDebugMessage::Severities)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_OPENGL_EXPORT QDebug operator<<(QDebug debug, const QOpenGLDebugMessage &message);
+Q_OPENGL_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Source source);
+Q_OPENGL_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Type type);
+Q_OPENGL_EXPORT QDebug operator<<(QDebug debug, QOpenGLDebugMessage::Severity severity);
+#endif
+
+class QOpenGLDebugLoggerPrivate;
+
+class Q_OPENGL_EXPORT QOpenGLDebugLogger : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(LoggingMode loggingMode READ loggingMode)
+
+public:
+ enum LoggingMode {
+ AsynchronousLogging,
+ SynchronousLogging
+ };
+ Q_ENUM(LoggingMode)
+
+ explicit QOpenGLDebugLogger(QObject *parent = nullptr);
+ ~QOpenGLDebugLogger();
+
+ bool initialize();
+
+ bool isLogging() const;
+ LoggingMode loggingMode() const;
+
+ qint64 maximumMessageLength() const;
+
+ void pushGroup(const QString &name,
+ GLuint id = 0,
+ QOpenGLDebugMessage::Source source = QOpenGLDebugMessage::ApplicationSource);
+ void popGroup();
+
+ void enableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource,
+ QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType,
+ QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity);
+
+ void enableMessages(const QVector<GLuint> &ids,
+ QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource,
+ QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType);
+
+ void disableMessages(QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource,
+ QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType,
+ QOpenGLDebugMessage::Severities severities = QOpenGLDebugMessage::AnySeverity);
+
+ void disableMessages(const QVector<GLuint> &ids,
+ QOpenGLDebugMessage::Sources sources = QOpenGLDebugMessage::AnySource,
+ QOpenGLDebugMessage::Types types = QOpenGLDebugMessage::AnyType);
+
+ QList<QOpenGLDebugMessage> loggedMessages() const;
+
+public Q_SLOTS:
+ void logMessage(const QOpenGLDebugMessage &debugMessage);
+ void startLogging(LoggingMode loggingMode = AsynchronousLogging);
+ void stopLogging();
+
+Q_SIGNALS:
+ void messageLogged(const QOpenGLDebugMessage &debugMessage);
+
+private:
+ Q_DISABLE_COPY(QOpenGLDebugLogger)
+ Q_DECLARE_PRIVATE(QOpenGLDebugLogger)
+ Q_PRIVATE_SLOT(d_func(), void _q_contextAboutToBeDestroyed())
+};
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QOpenGLDebugMessage)
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLDEBUG_H
diff --git a/src/opengl/qopenglengineshadermanager.cpp b/src/opengl/qopenglengineshadermanager.cpp
new file mode 100644
index 0000000000..09bd9ff096
--- /dev/null
+++ b/src/opengl/qopenglengineshadermanager.cpp
@@ -0,0 +1,898 @@
+/****************************************************************************
+**
+** 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 "qopenglengineshadermanager_p.h"
+#include "qopenglengineshadersource_p.h"
+#include "qopenglpaintengine_p.h"
+#include <private/qopenglshadercache_p.h>
+
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtCore/qthreadstorage.h>
+
+#include <algorithm>
+
+#if defined(QT_DEBUG)
+#include <QMetaEnum>
+#endif
+
+// #define QT_GL_SHARED_SHADER_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLEngineSharedShadersResource : public QOpenGLSharedResource
+{
+public:
+ QOpenGLEngineSharedShadersResource(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , m_shaders(new QOpenGLEngineSharedShaders(ctx))
+ {
+ }
+
+ ~QOpenGLEngineSharedShadersResource()
+ {
+ delete m_shaders;
+ }
+
+ void invalidateResource() override
+ {
+ delete m_shaders;
+ m_shaders = nullptr;
+ }
+
+ void freeResource(QOpenGLContext *) override
+ {
+ }
+
+ QOpenGLEngineSharedShaders *shaders() const { return m_shaders; }
+
+private:
+ QOpenGLEngineSharedShaders *m_shaders;
+};
+
+class QOpenGLShaderStorage
+{
+public:
+ QOpenGLEngineSharedShaders *shadersForThread(QOpenGLContext *context) {
+ QOpenGLMultiGroupSharedResource *&shaders = m_storage.localData();
+ if (!shaders)
+ shaders = new QOpenGLMultiGroupSharedResource;
+ QOpenGLEngineSharedShadersResource *resource =
+ shaders->value<QOpenGLEngineSharedShadersResource>(context);
+ return resource ? resource->shaders() : nullptr;
+ }
+
+private:
+ QThreadStorage<QOpenGLMultiGroupSharedResource *> m_storage;
+};
+
+Q_GLOBAL_STATIC(QOpenGLShaderStorage, qt_shader_storage);
+
+QOpenGLEngineSharedShaders *QOpenGLEngineSharedShaders::shadersForContext(QOpenGLContext *context)
+{
+ return qt_shader_storage()->shadersForThread(context);
+}
+
+const char* QOpenGLEngineSharedShaders::qShaderSnippets[] = {
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0
+};
+
+QOpenGLEngineSharedShaders::QOpenGLEngineSharedShaders(QOpenGLContext* context)
+ : blitShaderProg(nullptr)
+ , simpleShaderProg(nullptr)
+{
+
+/*
+ Rather than having the shader source array statically initialised, it is initialised
+ here instead. This is to allow new shader names to be inserted or existing names moved
+ around without having to change the order of the glsl strings. It is hoped this will
+ make future hard-to-find runtime bugs more obvious and generally give more solid code.
+*/
+
+ // Check if the user has requested an OpenGL 3.2 Core Profile or higher
+ // and if so use GLSL 1.50 core shaders instead of legacy ones.
+ const QSurfaceFormat &fmt = context->format();
+ const bool isCoreProfile = fmt.profile() == QSurfaceFormat::CoreProfile && fmt.version() >= qMakePair(3,2);
+
+ const char** code = qShaderSnippets; // shortcut
+
+ if (isCoreProfile) {
+ code[MainVertexShader] = qopenglslMainVertexShader_core;
+ code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader_core;
+ code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader_core;
+
+ code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader_core;
+ code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader_core;
+ code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader_core;
+ code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader_core;
+ code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader_core;
+ code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader_core;
+ code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader_core;
+ code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader_core;
+ code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader_core;
+ code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader_core;
+ code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader_core;
+ code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader_core;
+ code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader_core;
+
+ code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO_core;
+ code[MainFragmentShader_M] = qopenglslMainFragmentShader_M_core;
+ code[MainFragmentShader_O] = qopenglslMainFragmentShader_O_core;
+ code[MainFragmentShader] = qopenglslMainFragmentShader_core;
+ code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays_core;
+
+ code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader_core;
+ code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader_core;
+ code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader_core;
+ code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader_core;
+ code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader_core;
+ code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader_core; // Calls "customShader", which must be appended
+ code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader_core;
+
+ code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader_core;
+ code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader_core;
+ code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader_core;
+ code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader_core;
+ code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader_core;
+ code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader_core;
+ code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader_core;
+
+ code[NoMaskFragmentShader] = "";
+ code[MaskFragmentShader] = qopenglslMaskFragmentShader_core;
+ code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1_core;
+ code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2_core;
+ code[RgbMaskWithGammaFragmentShader] = ""; //###
+ } else {
+ code[MainVertexShader] = qopenglslMainVertexShader;
+ code[MainWithTexCoordsVertexShader] = qopenglslMainWithTexCoordsVertexShader;
+ code[MainWithTexCoordsAndOpacityVertexShader] = qopenglslMainWithTexCoordsAndOpacityVertexShader;
+
+ code[UntransformedPositionVertexShader] = qopenglslUntransformedPositionVertexShader;
+ code[PositionOnlyVertexShader] = qopenglslPositionOnlyVertexShader;
+ code[ComplexGeometryPositionOnlyVertexShader] = qopenglslComplexGeometryPositionOnlyVertexShader;
+ code[PositionWithPatternBrushVertexShader] = qopenglslPositionWithPatternBrushVertexShader;
+ code[PositionWithLinearGradientBrushVertexShader] = qopenglslPositionWithLinearGradientBrushVertexShader;
+ code[PositionWithConicalGradientBrushVertexShader] = qopenglslPositionWithConicalGradientBrushVertexShader;
+ code[PositionWithRadialGradientBrushVertexShader] = qopenglslPositionWithRadialGradientBrushVertexShader;
+ code[PositionWithTextureBrushVertexShader] = qopenglslPositionWithTextureBrushVertexShader;
+ code[AffinePositionWithPatternBrushVertexShader] = qopenglslAffinePositionWithPatternBrushVertexShader;
+ code[AffinePositionWithLinearGradientBrushVertexShader] = qopenglslAffinePositionWithLinearGradientBrushVertexShader;
+ code[AffinePositionWithConicalGradientBrushVertexShader] = qopenglslAffinePositionWithConicalGradientBrushVertexShader;
+ code[AffinePositionWithRadialGradientBrushVertexShader] = qopenglslAffinePositionWithRadialGradientBrushVertexShader;
+ code[AffinePositionWithTextureBrushVertexShader] = qopenglslAffinePositionWithTextureBrushVertexShader;
+
+ code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO;
+ code[MainFragmentShader_M] = qopenglslMainFragmentShader_M;
+ code[MainFragmentShader_O] = qopenglslMainFragmentShader_O;
+ code[MainFragmentShader] = qopenglslMainFragmentShader;
+ code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays;
+
+ code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader;
+ code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader;
+ code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader;
+ code[GrayscaleImageSrcFragmentShader] = qopenglslGrayscaleImageSrcFragmentShader;
+ code[AlphaImageSrcFragmentShader] = qopenglslAlphaImageSrcFragmentShader;
+ code[CustomImageSrcFragmentShader] = qopenglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
+ code[SolidBrushSrcFragmentShader] = qopenglslSolidBrushSrcFragmentShader;
+ code[TextureBrushSrcFragmentShader] = qopenglslTextureBrushSrcFragmentShader;
+ code[TextureBrushSrcWithPatternFragmentShader] = qopenglslTextureBrushSrcWithPatternFragmentShader;
+ code[PatternBrushSrcFragmentShader] = qopenglslPatternBrushSrcFragmentShader;
+ code[LinearGradientBrushSrcFragmentShader] = qopenglslLinearGradientBrushSrcFragmentShader;
+ code[RadialGradientBrushSrcFragmentShader] = qopenglslRadialGradientBrushSrcFragmentShader;
+ code[ConicalGradientBrushSrcFragmentShader] = qopenglslConicalGradientBrushSrcFragmentShader;
+ code[ShockingPinkSrcFragmentShader] = qopenglslShockingPinkSrcFragmentShader;
+
+ code[NoMaskFragmentShader] = "";
+ code[MaskFragmentShader] = qopenglslMaskFragmentShader;
+ code[RgbMaskFragmentShaderPass1] = qopenglslRgbMaskFragmentShaderPass1;
+ code[RgbMaskFragmentShaderPass2] = qopenglslRgbMaskFragmentShaderPass2;
+ code[RgbMaskWithGammaFragmentShader] = ""; //###
+ }
+
+ // The composition shaders are just layout qualifiers and the same
+ // for all profiles that support them.
+ code[NoCompositionModeFragmentShader] = "";
+ code[MultiplyCompositionModeFragmentShader] = qopenglslMultiplyCompositionModeFragmentShader;
+ code[ScreenCompositionModeFragmentShader] = qopenglslScreenCompositionModeFragmentShader;
+ code[OverlayCompositionModeFragmentShader] = qopenglslOverlayCompositionModeFragmentShader;
+ code[DarkenCompositionModeFragmentShader] = qopenglslDarkenCompositionModeFragmentShader;
+ code[LightenCompositionModeFragmentShader] = qopenglslLightenCompositionModeFragmentShader;
+ code[ColorDodgeCompositionModeFragmentShader] = qopenglslColorDodgeCompositionModeFragmentShader;
+ code[ColorBurnCompositionModeFragmentShader] = qopenglslColorBurnCompositionModeFragmentShader;
+ code[HardLightCompositionModeFragmentShader] = qopenglslHardLightCompositionModeFragmentShader;
+ code[SoftLightCompositionModeFragmentShader] = qopenglslSoftLightCompositionModeFragmentShader;
+ code[DifferenceCompositionModeFragmentShader] = qopenglslDifferenceCompositionModeFragmentShader;
+ code[ExclusionCompositionModeFragmentShader] = qopenglslExclusionCompositionModeFragmentShader;
+
+#if defined(QT_DEBUG)
+ // Check that all the elements have been filled:
+ for (int i = 0; i < TotalSnippetCount; ++i) {
+ if (Q_UNLIKELY(!qShaderSnippets[i])) {
+ qFatal("Shader snippet for %s (#%d) is missing!",
+ snippetNameStr(SnippetName(i)).constData(), i);
+ }
+ }
+#endif
+
+ QByteArray vertexSource;
+ QByteArray fragSource;
+
+ // Compile up the simple shader:
+#ifdef Q_OS_WASM
+ vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
+ vertexSource.append(qShaderSnippets[MainVertexShader]);
+#else
+ vertexSource.append(qShaderSnippets[MainVertexShader]);
+ vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
+#endif
+ fragSource.append(qShaderSnippets[MainFragmentShader]);
+ fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
+
+ simpleShaderProg = new QOpenGLShaderProgram;
+
+ CachedShader simpleShaderCache(fragSource, vertexSource);
+
+ bool inCache = simpleShaderCache.load(simpleShaderProg, context);
+
+ if (!inCache) {
+ if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
+ qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
+ if (!simpleShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
+ qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
+
+ simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+ simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
+ }
+
+ simpleShaderProg->link();
+
+ if (Q_UNLIKELY(!simpleShaderProg->isLinked())) {
+ qCritical("Errors linking simple shader: %s", qPrintable(simpleShaderProg->log()));
+ } else {
+ if (!inCache)
+ simpleShaderCache.store(simpleShaderProg, context);
+ }
+
+ // Compile the blit shader:
+ vertexSource.clear();
+ vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
+ vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]);
+
+ fragSource.clear();
+ fragSource.append(qShaderSnippets[MainFragmentShader]);
+ fragSource.append(qShaderSnippets[ImageSrcFragmentShader]);
+
+ blitShaderProg = new QOpenGLShaderProgram;
+
+ CachedShader blitShaderCache(fragSource, vertexSource);
+
+ inCache = blitShaderCache.load(blitShaderProg, context);
+
+ if (!inCache) {
+ if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource))
+ qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
+ if (!blitShaderProg->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource))
+ qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
+
+ blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ }
+
+ blitShaderProg->link();
+ if (Q_UNLIKELY(!blitShaderProg->isLinked())) {
+ qCritical("Errors linking blit shader: %s", qPrintable(blitShaderProg->log()));
+ } else {
+ if (!inCache)
+ blitShaderCache.store(blitShaderProg, context);
+ }
+
+#ifdef QT_GL_SHARED_SHADER_DEBUG
+ qDebug(" -> QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
+#endif
+}
+
+QOpenGLEngineSharedShaders::~QOpenGLEngineSharedShaders()
+{
+#ifdef QT_GL_SHARED_SHADER_DEBUG
+ qDebug(" -> ~QOpenGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
+#endif
+ qDeleteAll(cachedPrograms);
+ cachedPrograms.clear();
+
+ if (blitShaderProg) {
+ delete blitShaderProg;
+ blitShaderProg = nullptr;
+ }
+
+ if (simpleShaderProg) {
+ delete simpleShaderProg;
+ simpleShaderProg = nullptr;
+ }
+}
+
+#if defined (QT_DEBUG)
+QByteArray QOpenGLEngineSharedShaders::snippetNameStr(SnippetName name)
+{
+ QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
+ return QByteArray(m.valueToKey(name));
+}
+#endif
+
+// The address returned here will only be valid until next time this function is called.
+// The program is return bound.
+QOpenGLEngineShaderProg *QOpenGLEngineSharedShaders::findProgramInCache(const QOpenGLEngineShaderProg &prog)
+{
+ for (int i = 0; i < cachedPrograms.size(); ++i) {
+ QOpenGLEngineShaderProg *cachedProg = cachedPrograms[i];
+ if (*cachedProg == prog) {
+ // Move the program to the top of the list as a poor-man's cache algo
+ cachedPrograms.move(i, 0);
+ cachedProg->program->bind();
+ return cachedProg;
+ }
+ }
+
+ QScopedPointer<QOpenGLEngineShaderProg> newProg;
+
+ do {
+ QByteArray fragSource;
+ // Insert the custom stage before the srcPixel shader to work around an ATI driver bug
+ // where you cannot forward declare a function that takes a sampler as argument.
+ if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
+ fragSource.append(prog.customStageSource);
+ fragSource.append(qShaderSnippets[prog.mainFragShader]);
+ fragSource.append(qShaderSnippets[prog.srcPixelFragShader]);
+ if (prog.compositionFragShader)
+ fragSource.append(qShaderSnippets[prog.compositionFragShader]);
+ if (prog.maskFragShader)
+ fragSource.append(qShaderSnippets[prog.maskFragShader]);
+
+ QByteArray vertexSource;
+#ifdef Q_OS_WASM
+ vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
+ vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
+#else
+ vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
+ vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
+#endif
+ QScopedPointer<QOpenGLShaderProgram> shaderProgram(new QOpenGLShaderProgram);
+
+ CachedShader shaderCache(fragSource, vertexSource);
+ bool inCache = shaderCache.load(shaderProgram.data(), QOpenGLContext::currentContext());
+
+ if (!inCache) {
+ if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vertexSource)) {
+ QByteArray description;
+#if defined(QT_DEBUG)
+ description.append("Vertex shader: main=");
+ description.append(snippetNameStr(prog.mainVertexShader));
+ description.append(", position=");
+ description.append(snippetNameStr(prog.positionVertexShader));
+#endif
+ qWarning("Warning: \"%s\" failed to compile!", description.constData());
+ break;
+ }
+ if (!shaderProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fragSource)) {
+ QByteArray description;
+#if defined(QT_DEBUG)
+ description.append("Fragment shader: main=");
+ description.append(snippetNameStr(prog.mainFragShader));
+ description.append(", srcPixel=");
+ description.append(snippetNameStr(prog.srcPixelFragShader));
+ if (prog.compositionFragShader) {
+ description.append(", composition=");
+ description.append(snippetNameStr(prog.compositionFragShader));
+ }
+ if (prog.maskFragShader) {
+ description.append(", mask=");
+ description.append(snippetNameStr(prog.maskFragShader));
+ }
+#endif
+ qWarning("Warning: \"%s\" failed to compile!", description.constData());
+ break;
+ }
+
+ // We have to bind the vertex attribute names before the program is linked:
+ shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ if (prog.useTextureCoords)
+ shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ if (prog.useOpacityAttribute)
+ shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
+ if (prog.usePmvMatrixAttribute) {
+ shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+ shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+ shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
+ }
+ }
+
+ newProg.reset(new QOpenGLEngineShaderProg(prog));
+ newProg->program = shaderProgram.take();
+
+ newProg->program->link();
+ if (newProg->program->isLinked()) {
+ if (!inCache)
+ shaderCache.store(newProg->program, QOpenGLContext::currentContext());
+ } else {
+ QString error;
+ error = QLatin1String("Shader program failed to link")
+ + QLatin1String(" Error Log:\n")
+ + QLatin1String(" ") + newProg->program->log();
+ qWarning() << error;
+ break;
+ }
+
+ newProg->program->bind();
+
+ if (newProg->maskFragShader != QOpenGLEngineSharedShaders::NoMaskFragmentShader) {
+ GLuint location = newProg->program->uniformLocation("maskTexture");
+ newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT);
+ }
+
+ if (cachedPrograms.count() > 30) {
+ // The cache is full, so delete the last 5 programs in the list.
+ // These programs will be least used, as a program us bumped to
+ // the top of the list when it's used.
+ for (int i = 0; i < 5; ++i) {
+ delete cachedPrograms.last();
+ cachedPrograms.removeLast();
+ }
+ }
+
+ cachedPrograms.insert(0, newProg.data());
+ } while (false);
+
+ return newProg.take();
+}
+
+void QOpenGLEngineSharedShaders::cleanupCustomStage(QOpenGLCustomShaderStage* stage)
+{
+ auto hasStageAsCustomShaderSouce = [stage](QOpenGLEngineShaderProg *cachedProg) -> bool {
+ if (cachedProg->customStageSource == stage->source()) {
+ delete cachedProg;
+ return true;
+ }
+ return false;
+ };
+ cachedPrograms.erase(std::remove_if(cachedPrograms.begin(), cachedPrograms.end(),
+ hasStageAsCustomShaderSouce),
+ cachedPrograms.end());
+}
+
+
+QOpenGLEngineShaderManager::QOpenGLEngineShaderManager(QOpenGLContext* context)
+ : ctx(context),
+ shaderProgNeedsChanging(true),
+ complexGeometry(false),
+ srcPixelType(Qt::NoBrush),
+ opacityMode(NoOpacity),
+ maskType(NoMask),
+ compositionMode(QPainter::CompositionMode_SourceOver),
+ customSrcStage(nullptr),
+ currentShaderProg(nullptr)
+{
+ sharedShaders = QOpenGLEngineSharedShaders::shadersForContext(context);
+}
+
+QOpenGLEngineShaderManager::~QOpenGLEngineShaderManager()
+{
+ //###
+ removeCustomStage();
+}
+
+GLuint QOpenGLEngineShaderManager::getUniformLocation(Uniform id)
+{
+ if (!currentShaderProg)
+ return 0;
+
+ QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
+ if (uniformLocations.isEmpty())
+ uniformLocations.fill(GLuint(-1), NumUniforms);
+
+ const char uniformNames[][26] = {
+ "imageTexture",
+ "patternColor",
+ "globalOpacity",
+ "depth",
+ "maskTexture",
+ "fragmentColor",
+ "linearData",
+ "angle",
+ "halfViewportSize",
+ "fmp",
+ "fmp2_m_radius2",
+ "inverse_2_fmp2_m_radius2",
+ "sqrfr",
+ "bradius",
+ "invertedTextureSize",
+ "brushTransform",
+ "brushTexture",
+ "matrix"
+ };
+
+ if (uniformLocations.at(id) == GLuint(-1))
+ uniformLocations[id] = currentShaderProg->program->uniformLocation(uniformNames[id]);
+
+ return uniformLocations.at(id);
+}
+
+
+void QOpenGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType)
+{
+ Q_UNUSED(transformType); // Currently ignored
+}
+
+void QOpenGLEngineShaderManager::setDirty()
+{
+ shaderProgNeedsChanging = true;
+}
+
+void QOpenGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
+{
+ Q_ASSERT(style != Qt::NoBrush);
+ if (srcPixelType == PixelSrcType(style))
+ return;
+
+ srcPixelType = style;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QOpenGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
+{
+ if (srcPixelType == type)
+ return;
+
+ srcPixelType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QOpenGLEngineShaderManager::setOpacityMode(OpacityMode mode)
+{
+ if (opacityMode == mode)
+ return;
+
+ opacityMode = mode;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QOpenGLEngineShaderManager::setMaskType(MaskType type)
+{
+ if (maskType == type)
+ return;
+
+ maskType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QOpenGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
+{
+ if (compositionMode == mode)
+ return;
+
+ bool wasAdvanced = compositionMode > QPainter::CompositionMode_Plus;
+ bool isAdvanced = mode > QPainter::CompositionMode_Plus;
+
+ compositionMode = mode;
+ shaderProgNeedsChanging = shaderProgNeedsChanging || wasAdvanced || isAdvanced;
+}
+
+void QOpenGLEngineShaderManager::setCustomStage(QOpenGLCustomShaderStage* stage)
+{
+ if (customSrcStage)
+ removeCustomStage();
+ customSrcStage = stage;
+ shaderProgNeedsChanging = true;
+}
+
+void QOpenGLEngineShaderManager::removeCustomStage()
+{
+ if (customSrcStage)
+ customSrcStage->setInactive();
+ customSrcStage = nullptr;
+ shaderProgNeedsChanging = true;
+}
+
+QOpenGLShaderProgram* QOpenGLEngineShaderManager::currentProgram()
+{
+ if (currentShaderProg)
+ return currentShaderProg->program;
+ else
+ return sharedShaders->simpleProgram();
+}
+
+void QOpenGLEngineShaderManager::useSimpleProgram()
+{
+ sharedShaders->simpleProgram()->bind();
+ QOpenGLContextPrivate* ctx_d = ctx->d_func();
+ Q_UNUSED(ctx_d);
+
+ QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
+
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
+
+ shaderProgNeedsChanging = true;
+}
+
+void QOpenGLEngineShaderManager::useBlitProgram()
+{
+ sharedShaders->blitProgram()->bind();
+ QOpenGLContextPrivate* ctx_d = ctx->d_func();
+ QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
+ shaderProgNeedsChanging = true;
+}
+
+QOpenGLShaderProgram* QOpenGLEngineShaderManager::simpleProgram()
+{
+ return sharedShaders->simpleProgram();
+}
+
+QOpenGLShaderProgram* QOpenGLEngineShaderManager::blitProgram()
+{
+ return sharedShaders->blitProgram();
+}
+
+
+
+// Select & use the correct shader program using the current state.
+// Returns \c true if program needed changing.
+bool QOpenGLEngineShaderManager::useCorrectShaderProg()
+{
+ if (!shaderProgNeedsChanging)
+ return false;
+
+ bool useCustomSrc = customSrcStage != nullptr;
+ if (useCustomSrc && srcPixelType != QOpenGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
+ useCustomSrc = false;
+ qWarning("QOpenGLEngineShaderManager - Ignoring custom shader stage for non image src");
+ }
+
+ QOpenGLEngineShaderProg requiredProgram;
+
+ bool texCoords = false;
+
+ // Choose vertex shader shader position function (which typically also sets
+ // varyings) and the source pixel (srcPixel) fragment shader function:
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::InvalidSnippetName;
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::InvalidSnippetName;
+ bool isAffine = brushTransform.isAffine();
+ if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
+ if (isAffine)
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
+ else
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
+
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::PatternBrushSrcFragmentShader;
+ }
+ else switch (srcPixelType) {
+ default:
+ case Qt::NoBrush:
+ qFatal("QOpenGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
+ break;
+ case QOpenGLEngineShaderManager::ImageSrc:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ texCoords = true;
+ break;
+ case QOpenGLEngineShaderManager::NonPremultipliedImageSrc:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ texCoords = true;
+ break;
+ case QOpenGLEngineShaderManager::GrayscaleImageSrc:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::GrayscaleImageSrcFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ texCoords = true;
+ break;
+ case QOpenGLEngineShaderManager::AlphaImageSrc:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::AlphaImageSrcFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ texCoords = true;
+ break;
+ case QOpenGLEngineShaderManager::PatternSrc:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ texCoords = true;
+ break;
+ case QOpenGLEngineShaderManager::TextureSrcWithPattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
+ requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
+ : QOpenGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
+ break;
+ case Qt::SolidPattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::SolidBrushSrcFragmentShader;
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::PositionOnlyVertexShader;
+ break;
+ case Qt::LinearGradientPattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
+ requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
+ : QOpenGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
+ break;
+ case Qt::ConicalGradientPattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
+ requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
+ : QOpenGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
+ break;
+ case Qt::RadialGradientPattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
+ requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
+ : QOpenGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
+ break;
+ case Qt::TexturePattern:
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::TextureBrushSrcFragmentShader;
+ requiredProgram.positionVertexShader = isAffine ? QOpenGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
+ : QOpenGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
+ break;
+ };
+
+ if (useCustomSrc) {
+ requiredProgram.srcPixelFragShader = QOpenGLEngineSharedShaders::CustomImageSrcFragmentShader;
+ requiredProgram.customStageSource = customSrcStage->source();
+ }
+
+ const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
+ const bool hasMask = maskType != QOpenGLEngineShaderManager::NoMask;
+
+ // Choose fragment shader main function:
+ if (opacityMode == AttributeOpacity) {
+ Q_ASSERT(!hasCompose && !hasMask);
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_ImageArrays;
+ } else {
+ bool useGlobalOpacity = (opacityMode == UniformOpacity);
+ if (hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_MO;
+ if (hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_M;
+ if (!hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_O;
+ if (!hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader;
+ }
+
+ if (hasMask) {
+ if (maskType == PixelMask) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::MaskFragmentShader;
+ texCoords = true;
+ } else if (maskType == SubPixelMaskPass1) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
+ texCoords = true;
+ } else if (maskType == SubPixelMaskPass2) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
+ texCoords = true;
+ } else if (maskType == SubPixelWithGammaMask) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
+ texCoords = true;
+ } else {
+ qCritical("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
+ }
+ } else {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::NoMaskFragmentShader;
+ }
+
+ if (hasCompose) {
+ switch (compositionMode) {
+ case QPainter::CompositionMode_Multiply:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Screen:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Overlay:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Darken:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Lighten:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::LightenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_HardLight:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Difference:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
+ break;
+ default:
+ qWarning("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
+ }
+ } else {
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::NoCompositionModeFragmentShader;
+ }
+
+ // Choose vertex shader main function
+ if (opacityMode == AttributeOpacity) {
+ Q_ASSERT(texCoords);
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
+ } else if (texCoords) {
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsVertexShader;
+ } else {
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainVertexShader;
+ }
+ requiredProgram.useTextureCoords = texCoords;
+ requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
+ if (complexGeometry && srcPixelType == Qt::SolidPattern) {
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader;
+ requiredProgram.usePmvMatrixAttribute = false;
+ } else {
+ requiredProgram.usePmvMatrixAttribute = true;
+
+ // Force complexGeometry off, since we currently don't support that mode for
+ // non-solid brushes
+ complexGeometry = false;
+ }
+
+ // At this point, requiredProgram is fully populated so try to find the program in the cache
+ currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
+
+ if (currentShaderProg && useCustomSrc) {
+ customSrcStage->setUniforms(currentShaderProg->program);
+ }
+
+ // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it
+ // doesn't use are disabled)
+ QOpenGLContextPrivate* ctx_d = ctx->d_func();
+ QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
+
+ shaderProgNeedsChanging = false;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/qopenglengineshadermanager_p.h
index d23b3ad550..71e6214278 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
+++ b/src/opengl/qopenglengineshadermanager_p.h
@@ -53,9 +53,9 @@
==============
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
+ this works fine. On ES, QOpenGLShader & QOpenGLShaderProgram will make partial
+ shaders work by concatenating the source in each QOpenGLShader and compiling
+ it as a single shader. This is abstracted nicely by QOpenGLShaderProgram and
the GL2 engine doesn't need to worry about it.
Generally, there's two vertex shader objects. The position shaders are
@@ -85,21 +85,21 @@
correction is needed and a simpler vertex shader can be used instead.
So there are the following "main" vertex shaders:
- qglslMainVertexShader
- qglslMainWithTexCoordsVertexShader
+ qopenglslMainVertexShader
+ qopenglslMainWithTexCoordsVertexShader
And the following position vertex shaders:
- qglslPositionOnlyVertexShader
- qglslPositionWithTextureBrushVertexShader
- qglslPositionWithPatternBrushVertexShader
- qglslPositionWithLinearGradientBrushVertexShader
- qglslPositionWithRadialGradientBrushVertexShader
- qglslPositionWithConicalGradientBrushVertexShader
- qglslAffinePositionWithTextureBrushVertexShader
- qglslAffinePositionWithPatternBrushVertexShader
- qglslAffinePositionWithLinearGradientBrushVertexShader
- qglslAffinePositionWithRadialGradientBrushVertexShader
- qglslAffinePositionWithConicalGradientBrushVertexShader
+ qopenglslPositionOnlyVertexShader
+ qopenglslPositionWithTextureBrushVertexShader
+ qopenglslPositionWithPatternBrushVertexShader
+ qopenglslPositionWithLinearGradientBrushVertexShader
+ qopenglslPositionWithRadialGradientBrushVertexShader
+ qopenglslPositionWithConicalGradientBrushVertexShader
+ qopenglslAffinePositionWithTextureBrushVertexShader
+ qopenglslAffinePositionWithPatternBrushVertexShader
+ qopenglslAffinePositionWithLinearGradientBrushVertexShader
+ qopenglslAffinePositionWithRadialGradientBrushVertexShader
+ qopenglslAffinePositionWithConicalGradientBrushVertexShader
Leading to 23 possible vertex shaders
@@ -126,36 +126,36 @@
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
+ qopenglslImageSrcFragShader
+ qopenglslImageSrcWithPatternFragShader
+ qopenglslNonPremultipliedImageSrcFragShader
+ qopenglslSolidBrushSrcFragShader
+ qopenglslTextureBrushSrcFragShader
+ qopenglslTextureBrushWithPatternFragShader
+ qopenglslPatternBrushSrcFragShader
+ qopenglslLinearGradientBrushSrcFragShader
+ qopenglslRadialGradientBrushSrcFragShader
+ qopenglslConicalGradientBrushSrcFragShader
NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
- qglslMaskFragmentShader
- qglslRgbMaskFragmentShaderPass1
- qglslRgbMaskFragmentShaderPass2
- qglslRgbMaskWithGammaFragmentShader
+ qopenglslMaskFragmentShader
+ qopenglslRgbMaskFragmentShaderPass1
+ qopenglslRgbMaskFragmentShaderPass2
+ qopenglslRgbMaskWithGammaFragmentShader
Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
- qglslColorBurnCompositionModeFragmentShader
- qglslColorDodgeCompositionModeFragmentShader
- qglslDarkenCompositionModeFragmentShader
- qglslDifferenceCompositionModeFragmentShader
- qglslExclusionCompositionModeFragmentShader
- qglslHardLightCompositionModeFragmentShader
- qglslLightenCompositionModeFragmentShader
- qglslMultiplyCompositionModeFragmentShader
- qglslOverlayCompositionModeFragmentShader
- qglslScreenCompositionModeFragmentShader
- qglslSoftLightCompositionModeFragmentShader
+ qopenglslColorBurnCompositionModeFragmentShader
+ qopenglslColorDodgeCompositionModeFragmentShader
+ qopenglslDarkenCompositionModeFragmentShader
+ qopenglslDifferenceCompositionModeFragmentShader
+ qopenglslExclusionCompositionModeFragmentShader
+ qopenglslHardLightCompositionModeFragmentShader
+ qopenglslLightenCompositionModeFragmentShader
+ qopenglslMultiplyCompositionModeFragmentShader
+ qopenglslOverlayCompositionModeFragmentShader
+ qopenglslScreenCompositionModeFragmentShader
+ qopenglslSoftLightCompositionModeFragmentShader
Note: In the future, some GLSL compilers will support an extension allowing
@@ -183,14 +183,14 @@
gl_FragColor = srcPixel();
Called:
- qglslMainFragmentShader_CMO
- qglslMainFragmentShader_CM
- qglslMainFragmentShader_MO
- qglslMainFragmentShader_M
- qglslMainFragmentShader_CO
- qglslMainFragmentShader_C
- qglslMainFragmentShader_O
- qglslMainFragmentShader
+ qopenglslMainFragmentShader_CMO
+ qopenglslMainFragmentShader_CM
+ qopenglslMainFragmentShader_MO
+ qopenglslMainFragmentShader_M
+ qopenglslMainFragmentShader_CO
+ qopenglslMainFragmentShader_C
+ qopenglslMainFragmentShader_O
+ qopenglslMainFragmentShader
Where:
M = Mask
@@ -205,7 +205,7 @@
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
+ (QOpenGLCustomShaderStage). The shader will implement a pre-defined method name
which Qt's fragment pipeline will call:
lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords)
@@ -217,31 +217,31 @@
will be respected when using the custom shader hook.
*/
-#ifndef QGLENGINE_SHADER_MANAGER_H
-#define QGLENGINE_SHADER_MANAGER_H
+#ifndef QOPENGLENGINE_SHADER_MANAGER_H
+#define QOPENGLENGINE_SHADER_MANAGER_H
-#include <QGLShader>
-#include <QGLShaderProgram>
+#include <QOpenGLShader>
+#include <QOpenGLShaderProgram>
#include <QPainter>
-#include <private/qgl_p.h>
-#include <private/qglcustomshaderstage_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglcustomshaderstage_p.h>
QT_BEGIN_NAMESPACE
/*
-struct QGLEngineCachedShaderProg
+struct QOpenGLEngineCachedShaderProg
{
- QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
- QGLEngineShaderManager::ShaderName vertexPosition,
- QGLEngineShaderManager::ShaderName fragMain,
- QGLEngineShaderManager::ShaderName pixelSrc,
- QGLEngineShaderManager::ShaderName mask,
- QGLEngineShaderManager::ShaderName composition);
+ QOpenGLEngineCachedShaderProg(QOpenGLEngineShaderManager::ShaderName vertexMain,
+ QOpenGLEngineShaderManager::ShaderName vertexPosition,
+ QOpenGLEngineShaderManager::ShaderName fragMain,
+ QOpenGLEngineShaderManager::ShaderName pixelSrc,
+ QOpenGLEngineShaderManager::ShaderName mask,
+ QOpenGLEngineShaderManager::ShaderName composition);
int cacheKey;
- QGLShaderProgram* program;
+ QOpenGLShaderProgram* program;
}
*/
@@ -252,9 +252,9 @@ 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 QOpenGLEngineShaderProg;
-class Q_OPENGL_EXPORT QGLEngineSharedShaders
+class Q_OPENGL_EXPORT QOpenGLEngineSharedShaders
{
Q_GADGET
public:
@@ -280,12 +280,8 @@ public:
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,
@@ -294,6 +290,8 @@ public:
ImageSrcFragmentShader,
ImageSrcWithPatternFragmentShader,
NonPremultipliedImageSrcFragmentShader,
+ GrayscaleImageSrcFragmentShader,
+ AlphaImageSrcFragmentShader,
CustomImageSrcFragmentShader,
SolidBrushSrcFragmentShader,
TextureBrushSrcFragmentShader,
@@ -328,7 +326,7 @@ public:
TotalSnippetCount, InvalidSnippetName
};
#if defined (QT_DEBUG)
- Q_ENUMS(SnippetName)
+ Q_ENUM(SnippetName)
static QByteArray snippetNameStr(SnippetName snippetName);
#endif
@@ -342,52 +340,51 @@ public:
const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
*/
- QGLEngineSharedShaders(const QGLContext *context);
- ~QGLEngineSharedShaders();
+ QOpenGLEngineSharedShaders(QOpenGLContext *context);
+ ~QOpenGLEngineSharedShaders();
- QGLShaderProgram *simpleProgram() { return simpleShaderProg; }
- QGLShaderProgram *blitProgram() { return blitShaderProg; }
+ QOpenGLShaderProgram *simpleProgram() { return simpleShaderProg; }
+ QOpenGLShaderProgram *blitProgram() { return blitShaderProg; }
// Compile the program if it's not already in the cache, return the item in the cache.
- QGLEngineShaderProg *findProgramInCache(const QGLEngineShaderProg &prog);
+ QOpenGLEngineShaderProg *findProgramInCache(const QOpenGLEngineShaderProg &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);
+ static QOpenGLEngineSharedShaders *shadersForContext(QOpenGLContext *context);
// Ideally, this would be static and cleanup all programs in all contexts which
// contain the custom code. Currently it is just a hint and we rely on deleted
// custom shaders being cleaned up by being kicked out of the cache when it's
// full.
- void cleanupCustomStage(QGLCustomShaderStage* stage);
+ void cleanupCustomStage(QOpenGLCustomShaderStage* stage);
private:
- QGLShaderProgram *blitShaderProg;
- QGLShaderProgram *simpleShaderProg;
- QList<QGLEngineShaderProg*> cachedPrograms;
- QList<QGLShader *> shaders;
+ QOpenGLShaderProgram *blitShaderProg;
+ QOpenGLShaderProgram *simpleShaderProg;
+ QList<QOpenGLEngineShaderProg*> cachedPrograms;
static const char* qShaderSnippets[TotalSnippetCount];
};
-class QGLEngineShaderProg
+class QOpenGLEngineShaderProg
{
public:
- QGLEngineShaderProg() : program(nullptr) {}
+ QOpenGLEngineShaderProg() : program(nullptr) {}
- ~QGLEngineShaderProg() {
+ ~QOpenGLEngineShaderProg() {
if (program)
delete program;
}
- QGLEngineSharedShaders::SnippetName mainVertexShader;
- QGLEngineSharedShaders::SnippetName positionVertexShader;
- QGLEngineSharedShaders::SnippetName mainFragShader;
- QGLEngineSharedShaders::SnippetName srcPixelFragShader;
- QGLEngineSharedShaders::SnippetName maskFragShader;
- QGLEngineSharedShaders::SnippetName compositionFragShader;
+ QOpenGLEngineSharedShaders::SnippetName mainVertexShader;
+ QOpenGLEngineSharedShaders::SnippetName positionVertexShader;
+ QOpenGLEngineSharedShaders::SnippetName mainFragShader;
+ QOpenGLEngineSharedShaders::SnippetName srcPixelFragShader;
+ QOpenGLEngineSharedShaders::SnippetName maskFragShader;
+ QOpenGLEngineSharedShaders::SnippetName compositionFragShader;
QByteArray customStageSource; //TODO: Decent cache key for custom stages
- QGLShaderProgram* program;
+ QOpenGLShaderProgram* program;
QVector<uint> uniformLocations;
@@ -395,7 +392,7 @@ public:
bool useOpacityAttribute;
bool usePmvMatrixAttribute;
- bool operator==(const QGLEngineShaderProg& other) const {
+ bool operator==(const QOpenGLEngineShaderProg& other) const {
// We don't care about the program
return ( mainVertexShader == other.mainVertexShader &&
positionVertexShader == other.positionVertexShader &&
@@ -408,19 +405,21 @@ public:
}
};
-class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject
+class Q_OPENGL_EXPORT QOpenGLEngineShaderManager : public QObject
{
Q_OBJECT
public:
- QGLEngineShaderManager(QGLContext* context);
- ~QGLEngineShaderManager();
+ QOpenGLEngineShaderManager(QOpenGLContext* context);
+ ~QOpenGLEngineShaderManager();
enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask};
enum PixelSrcType {
ImageSrc = Qt::TexturePattern+1,
NonPremultipliedImageSrc = Qt::TexturePattern+2,
PatternSrc = Qt::TexturePattern+3,
- TextureSrcWithPattern = Qt::TexturePattern+4
+ TextureSrcWithPattern = Qt::TexturePattern+4,
+ GrayscaleImageSrc = Qt::TexturePattern+5,
+ AlphaImageSrc = Qt::TexturePattern+6,
};
enum Uniform {
@@ -442,7 +441,6 @@ public:
BrushTransform,
BrushTexture,
Matrix,
- TranslateZ,
NumUniforms
};
@@ -461,7 +459,7 @@ public:
void setOpacityMode(OpacityMode);
void setMaskType(MaskType);
void setCompositionMode(QPainter::CompositionMode);
- void setCustomStage(QGLCustomShaderStage* stage);
+ void setCustomStage(QOpenGLCustomShaderStage* stage);
void removeCustomStage();
GLuint getUniformLocation(Uniform id);
@@ -481,14 +479,14 @@ public:
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
+ QOpenGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
+ QOpenGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
+ QOpenGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
- QGLEngineSharedShaders* sharedShaders;
+ QOpenGLEngineSharedShaders* sharedShaders;
private:
- QGLContext* ctx;
+ QOpenGLContext* ctx;
bool shaderProgNeedsChanging;
bool complexGeometry;
@@ -498,11 +496,11 @@ private:
OpacityMode opacityMode;
MaskType maskType;
QPainter::CompositionMode compositionMode;
- QGLCustomShaderStage* customSrcStage;
+ QOpenGLCustomShaderStage* customSrcStage;
- QGLEngineShaderProg* currentShaderProg;
+ QOpenGLEngineShaderProg* currentShaderProg;
};
QT_END_NAMESPACE
-#endif //QGLENGINE_SHADER_MANAGER_H
+#endif //QOPENGLENGINE_SHADER_MANAGER_H
diff --git a/src/opengl/qopenglengineshadersource_p.h b/src/opengl/qopenglengineshadersource_p.h
new file mode 100644
index 0000000000..49d17c8d79
--- /dev/null
+++ b/src/opengl/qopenglengineshadersource_p.h
@@ -0,0 +1,969 @@
+/****************************************************************************
+**
+** 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 QOPENGL_ENGINE_SHADER_SOURCE_H
+#define QOPENGL_ENGINE_SHADER_SOURCE_H
+
+#include "qopenglengineshadermanager_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+static const char* const qopenglslMainVertexShader = "\n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ }\n";
+
+static const char* const qopenglslMainWithTexCoordsVertexShader = "\n\
+ attribute highp vec2 textureCoordArray; \n\
+ varying highp vec2 textureCoords; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ }\n";
+
+static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader = "\n\
+ attribute highp vec2 textureCoordArray; \n\
+ attribute lowp float opacityArray; \n\
+ varying highp vec2 textureCoords; \n\
+ varying lowp float opacity; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ opacity = opacityArray; \n\
+ }\n";
+
+// NOTE: We let GL do the perspective correction so texture lookups in the fragment
+// shader are also perspective corrected.
+static const char* const qopenglslPositionOnlyVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
+ }\n";
+
+static const char* const qopenglslComplexGeometryPositionOnlyVertexShader = "\n\
+ uniform highp mat3 matrix; \n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ void setPosition(void) \n\
+ { \n\
+ gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\
+ } \n";
+
+static const char* const qopenglslUntransformedPositionVertexShader = "\n\
+ attribute highp vec4 vertexCoordsArray; \n\
+ void setPosition(void) \n\
+ { \n\
+ gl_Position = vertexCoordsArray; \n\
+ }\n";
+
+// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
+static const char* const qopenglslPositionWithPatternBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec2 invertedTextureSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 patternTexCoords; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithPatternBrushVertexShader
+ = qopenglslPositionWithPatternBrushVertexShader;
+
+static const char* const qopenglslPatternBrushSrcFragmentShader = "\n\
+ uniform sampler2D brushTexture; \n\
+ uniform lowp vec4 patternColor; \n\
+ varying highp vec2 patternTexCoords;\n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\
+ }\n";
+
+
+// Linear Gradient Brush
+static const char* const qopenglslPositionWithLinearGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec3 linearData; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying mediump float index; \n\
+ void setPosition() \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader
+ = qopenglslPositionWithLinearGradientBrushVertexShader;
+
+static const char* const qopenglslLinearGradientBrushSrcFragmentShader = "\n\
+ uniform sampler2D brushTexture; \n\
+ varying mediump float index; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ mediump vec2 val = vec2(index, 0.5); \n\
+ return texture2D(brushTexture, val); \n\
+ }\n";
+
+
+// Conical Gradient Brush
+static const char* const qopenglslPositionWithConicalGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 A; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader
+ = qopenglslPositionWithConicalGradientBrushVertexShader;
+
+static const char* const qopenglslConicalGradientBrushSrcFragmentShader = "\n\
+ #define INVERSE_2PI 0.1591549430918953358 \n\
+ uniform sampler2D brushTexture; \n\
+ uniform mediump float angle; \n\
+ varying highp vec2 A; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ highp float t; \n\
+ if (abs(A.y) == abs(A.x)) \n\
+ t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
+ else \n\
+ t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
+ return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\
+ }\n";
+
+
+// Radial Gradient Brush
+static const char* const qopenglslPositionWithRadialGradientBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray;\n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ uniform highp vec2 fmp; \n\
+ uniform mediump vec3 bradius; \n\
+ varying highp float b; \n\
+ varying highp vec2 A; \n\
+ void setPosition(void) \n\
+ {\n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ b = bradius.x + 2.0 * dot(A, fmp); \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader
+ = qopenglslPositionWithRadialGradientBrushVertexShader;
+
+static const char* const qopenglslRadialGradientBrushSrcFragmentShader = "\n\
+ uniform sampler2D brushTexture; \n\
+ uniform highp float fmp2_m_radius2; \n\
+ uniform highp float inverse_2_fmp2_m_radius2; \n\
+ uniform highp float sqrfr; \n\
+ varying highp float b; \n\
+ varying highp vec2 A; \n\
+ uniform mediump vec3 bradius; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ highp float c = sqrfr-dot(A, A); \n\
+ highp float det = b*b - 4.0*fmp2_m_radius2*c; \n\
+ lowp vec4 result = vec4(0.0); \n\
+ if (det >= 0.0) { \n\
+ highp float detSqrt = sqrt(det); \n\
+ highp float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
+ if (bradius.y + w * bradius.z >= 0.0) \n\
+ result = texture2D(brushTexture, vec2(w, 0.5)); \n\
+ } \n\
+ return result; \n\
+ }\n";
+
+
+// Texture Brush
+static const char* const qopenglslPositionWithTextureBrushVertexShader = "\n\
+ attribute highp vec2 vertexCoordsArray; \n\
+ attribute highp vec3 pmvMatrix1; \n\
+ attribute highp vec3 pmvMatrix2; \n\
+ attribute highp vec3 pmvMatrix3; \n\
+ uniform mediump vec2 halfViewportSize; \n\
+ uniform highp vec2 invertedTextureSize; \n\
+ uniform highp mat3 brushTransform; \n\
+ varying highp vec2 brushTextureCoords; \n\
+ void setPosition(void) \n\
+ { \n\
+ highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithTextureBrushVertexShader
+ = qopenglslPositionWithTextureBrushVertexShader;
+
+static const char* const qopenglslTextureBrushSrcFragmentShader = "\n\
+ varying highp vec2 brushTextureCoords; \n\
+ uniform sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return texture2D(brushTexture, brushTextureCoords); \n\
+ }\n";
+
+static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader = "\n\
+ varying highp vec2 brushTextureCoords; \n\
+ uniform lowp vec4 patternColor; \n\
+ uniform sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\
+ }\n";
+
+// Solid Fill Brush
+static const char* const qopenglslSolidBrushSrcFragmentShader = "\n\
+ uniform lowp vec4 fragmentColor; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return fragmentColor; \n\
+ }\n";
+
+static const char* const qopenglslImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n"
+ "return texture2D(imageTexture, textureCoords); \n"
+ "}\n";
+
+static const char* const qopenglslCustomSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return customShader(imageTexture, textureCoords); \n\
+ }\n";
+
+static const char* const qopenglslImageSrcWithPatternFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform lowp vec4 patternColor; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\
+ }\n";
+
+static const char* const qopenglslNonPremultipliedImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\
+ sample.rgb = sample.rgb * sample.a; \n\
+ return sample; \n\
+ }\n";
+
+static const char* const qopenglslGrayscaleImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return texture2D(imageTexture, textureCoords).rrra; \n\
+ }\n";
+
+static const char* const qopenglslAlphaImageSrcFragmentShader = "\n\
+ varying highp vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return vec4(0, 0, 0, texture2D(imageTexture, textureCoords).r); \n\
+ }\n";
+
+static const char* const qopenglslShockingPinkSrcFragmentShader = "\n\
+ lowp vec4 srcPixel() \n\
+ { \n\
+ return vec4(0.98, 0.06, 0.75, 1.0); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_ImageArrays = "\n\
+ varying lowp float opacity; \n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel() * opacity; \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_MO = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_M = "\n\
+ lowp vec4 srcPixel(); \n\
+ lowp vec4 applyMask(lowp vec4); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = applyMask(srcPixel()); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_O = "\n\
+ uniform lowp float globalOpacity; \n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel()*globalOpacity; \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader = "\n\
+ lowp vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ gl_FragColor = srcPixel(); \n\
+ }\n";
+
+static const char* const qopenglslMaskFragmentShader = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ {\n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src * mask.a; \n\
+ }\n";
+
+// For source over with subpixel antialiasing, the final color is calculated per component as follows
+// (.a is alpha component, .c is red, green or blue component):
+// alpha = src.a * mask.c * opacity
+// dest.c = dest.c * (1 - alpha) + src.c * alpha
+//
+// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
+// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
+//
+// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
+
+// For source composition with subpixel antialiasing, the final color is calculated per component as follows:
+// alpha = src.a * mask.c * opacity
+// dest.c = dest.c * (1 - mask.c) + src.c * alpha
+//
+
+static const char* const qopenglslRgbMaskFragmentShaderPass1 = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ { \n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src.a * mask; \n\
+ }\n";
+
+static const char* const qopenglslRgbMaskFragmentShaderPass2 = "\n\
+ varying highp vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ lowp vec4 applyMask(lowp vec4 src) \n\
+ { \n\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
+ return src * mask; \n\
+ }\n";
+
+static const char* const qopenglslMultiplyCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_multiply) out;\n\
+ #endif\n";
+
+static const char* const qopenglslScreenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_screen) out;\n\
+ #endif\n";
+
+static const char* const qopenglslOverlayCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_overlay) out;\n\
+ #endif\n";
+
+static const char* const qopenglslDarkenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_darken) out;\n\
+ #endif\n";
+
+static const char* const qopenglslLightenCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_lighten) out;\n\
+ #endif\n";
+
+static const char* const qopenglslColorDodgeCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_colordodge) out;\n\
+ #endif\n";
+
+static const char* const qopenglslColorBurnCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_colorburn) out;\n\
+ #endif\n";
+
+static const char* const qopenglslHardLightCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_hardlight) out;\n\
+ #endif\n";
+
+static const char* const qopenglslSoftLightCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_softlight) out;\n\
+ #endif\n";
+
+static const char* const qopenglslDifferenceCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_difference) out;\n\
+ #endif\n";
+
+static const char* const qopenglslExclusionCompositionModeFragmentShader = "\n\
+ #ifdef GL_KHR_blend_equation_advanced\n\
+ layout(blend_support_exclusion) out;\n\
+ #endif\n";
+
+/*
+ Left to implement:
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+*/
+
+/*
+ OpenGL 3.2+ Core Profile shaders
+ The following shader snippets are copies of the snippets above
+ but use the modern GLSL 1.5 keywords. New shaders should make
+ a snippet for both profiles and add them appropriately in the
+ shader manager.
+*/
+static const char* const qopenglslMainVertexShader_core =
+ "#version 150 core\n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ }\n";
+
+static const char* const qopenglslMainWithTexCoordsVertexShader_core =
+ "#version 150 core\n\
+ in vec2 textureCoordArray; \n\
+ out vec2 textureCoords; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ }\n";
+
+static const char* const qopenglslMainWithTexCoordsAndOpacityVertexShader_core =
+ "#version 150 core\n\
+ in vec2 textureCoordArray; \n\
+ in float opacityArray; \n\
+ out vec2 textureCoords; \n\
+ out float opacity; \n\
+ void setPosition(); \n\
+ void main(void) \n\
+ { \n\
+ setPosition(); \n\
+ textureCoords = textureCoordArray; \n\
+ opacity = opacityArray; \n\
+ }\n";
+
+// NOTE: We let GL do the perspective correction so texture lookups in the fragment
+// shader are also perspective corrected.
+static const char* const qopenglslPositionOnlyVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ void setPosition(void) \n\
+ { \n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
+ }\n";
+
+static const char* const qopenglslComplexGeometryPositionOnlyVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ uniform mat3 matrix; \n\
+ void setPosition(void) \n\
+ { \n\
+ gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\
+ } \n";
+
+static const char* const qopenglslUntransformedPositionVertexShader_core = "\n\
+ in vec4 vertexCoordsArray; \n\
+ void setPosition(void) \n\
+ { \n\
+ gl_Position = vertexCoordsArray; \n\
+ }\n";
+
+// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
+static const char* const qopenglslPositionWithPatternBrushVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ out vec2 patternTexCoords; \n\
+ uniform vec2 halfViewportSize; \n\
+ uniform vec2 invertedTextureSize; \n\
+ uniform mat3 brushTransform; \n\
+ void setPosition(void) \n\
+ { \n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
+ float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithPatternBrushVertexShader_core
+ = qopenglslPositionWithPatternBrushVertexShader_core;
+
+static const char* const qopenglslPatternBrushSrcFragmentShader_core = "\n\
+ in vec2 patternTexCoords;\n\
+ uniform sampler2D brushTexture; \n\
+ uniform vec4 patternColor; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture(brushTexture, patternTexCoords).r); \n\
+ }\n";
+
+
+// Linear Gradient Brush
+static const char* const qopenglslPositionWithLinearGradientBrushVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ out float index; \n\
+ uniform vec2 halfViewportSize; \n\
+ uniform vec3 linearData; \n\
+ uniform mat3 brushTransform; \n\
+ void setPosition() \n\
+ { \n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithLinearGradientBrushVertexShader_core
+ = qopenglslPositionWithLinearGradientBrushVertexShader_core;
+
+static const char* const qopenglslLinearGradientBrushSrcFragmentShader_core = "\n\
+ uniform sampler2D brushTexture; \n\
+ in float index; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ vec2 val = vec2(index, 0.5); \n\
+ return texture(brushTexture, val); \n\
+ }\n";
+
+
+// Conical Gradient Brush
+static const char* const qopenglslPositionWithConicalGradientBrushVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ out vec2 A; \n\
+ uniform vec2 halfViewportSize; \n\
+ uniform mat3 brushTransform; \n\
+ void setPosition(void) \n\
+ { \n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithConicalGradientBrushVertexShader_core
+ = qopenglslPositionWithConicalGradientBrushVertexShader_core;
+
+static const char* const qopenglslConicalGradientBrushSrcFragmentShader_core = "\n\
+ #define INVERSE_2PI 0.1591549430918953358 \n\
+ in vec2 A; \n\
+ uniform sampler2D brushTexture; \n\
+ uniform float angle; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ float t; \n\
+ if (abs(A.y) == abs(A.x)) \n\
+ t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
+ else \n\
+ t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
+ return texture(brushTexture, vec2(t - floor(t), 0.5)); \n\
+ }\n";
+
+
+// Radial Gradient Brush
+static const char* const qopenglslPositionWithRadialGradientBrushVertexShader_core = "\n\
+ in vec2 vertexCoordsArray;\n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ out float b; \n\
+ out vec2 A; \n\
+ uniform vec2 halfViewportSize; \n\
+ uniform mat3 brushTransform; \n\
+ uniform vec2 fmp; \n\
+ uniform vec3 bradius; \n\
+ void setPosition(void) \n\
+ {\n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ A = hTexCoords.xy * invertedHTexCoordsZ; \n\
+ b = bradius.x + 2.0 * dot(A, fmp); \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithRadialGradientBrushVertexShader_core
+ = qopenglslPositionWithRadialGradientBrushVertexShader_core;
+
+static const char* const qopenglslRadialGradientBrushSrcFragmentShader_core = "\n\
+ in float b; \n\
+ in vec2 A; \n\
+ uniform sampler2D brushTexture; \n\
+ uniform float fmp2_m_radius2; \n\
+ uniform float inverse_2_fmp2_m_radius2; \n\
+ uniform float sqrfr; \n\
+ uniform vec3 bradius; \n\
+ \n\
+ vec4 srcPixel() \n\
+ { \n\
+ float c = sqrfr-dot(A, A); \n\
+ float det = b*b - 4.0*fmp2_m_radius2*c; \n\
+ vec4 result = vec4(0.0); \n\
+ if (det >= 0.0) { \n\
+ float detSqrt = sqrt(det); \n\
+ float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n\
+ if (bradius.y + w * bradius.z >= 0.0) \n\
+ result = texture(brushTexture, vec2(w, 0.5)); \n\
+ } \n\
+ return result; \n\
+ }\n";
+
+
+// Texture Brush
+static const char* const qopenglslPositionWithTextureBrushVertexShader_core = "\n\
+ in vec2 vertexCoordsArray; \n\
+ in vec3 pmvMatrix1; \n\
+ in vec3 pmvMatrix2; \n\
+ in vec3 pmvMatrix3; \n\
+ out vec2 brushTextureCoords; \n\
+ uniform vec2 halfViewportSize; \n\
+ uniform vec2 invertedTextureSize; \n\
+ uniform mat3 brushTransform; \n\
+ \n\
+ void setPosition(void) \n\
+ { \n\
+ mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
+ vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
+ gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
+ vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
+ vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
+ float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
+ gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
+ brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
+ }\n";
+
+static const char* const qopenglslAffinePositionWithTextureBrushVertexShader_core
+ = qopenglslPositionWithTextureBrushVertexShader_core;
+
+static const char* const qopenglslTextureBrushSrcFragmentShader_core = "\n\
+ in vec2 brushTextureCoords; \n\
+ uniform sampler2D brushTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return texture(brushTexture, brushTextureCoords); \n\
+ }\n";
+
+static const char* const qopenglslTextureBrushSrcWithPatternFragmentShader_core = "\n\
+ in vec2 brushTextureCoords; \n\
+ uniform vec4 patternColor; \n\
+ uniform sampler2D brushTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture(brushTexture, brushTextureCoords).r); \n\
+ }\n";
+
+// Solid Fill Brush
+static const char* const qopenglslSolidBrushSrcFragmentShader_core = "\n\
+ uniform vec4 fragmentColor; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return fragmentColor; \n\
+ }\n";
+
+static const char* const qopenglslImageSrcFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return texture(imageTexture, textureCoords); \n\
+ }\n";
+
+static const char* const qopenglslCustomSrcFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return customShader(imageTexture, textureCoords); \n\
+ }\n";
+
+static const char* const qopenglslImageSrcWithPatternFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform vec4 patternColor; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return patternColor * (1.0 - texture(imageTexture, textureCoords).r); \n\
+ }\n";
+
+static const char* const qopenglslNonPremultipliedImageSrcFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ vec4 sample = texture(imageTexture, textureCoords); \n\
+ sample.rgb = sample.rgb * sample.a; \n\
+ return sample; \n\
+ }\n";
+
+static const char* const qopenglslGrayscaleImageSrcFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return texture(imageTexture, textureCoords).rrra; \n\
+ }\n";
+
+static const char* const qopenglslAlphaImageSrcFragmentShader_core = "\n\
+ in vec2 textureCoords; \n\
+ uniform sampler2D imageTexture; \n\
+ vec4 srcPixel() \n\
+ { \n\
+ return vec4(0, 0, 0, texture(imageTexture, textureCoords).r); \n\
+ }\n";
+
+static const char* const qopenglslShockingPinkSrcFragmentShader_core = "\n\
+ vec4 srcPixel() \n\
+ { \n\
+ return vec4(0.98, 0.06, 0.75, 1.0); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_ImageArrays_core =
+ "#version 150 core\n\
+ in float opacity; \n\
+ out vec4 fragColor; \n\
+ vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ fragColor = srcPixel() * opacity; \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_MO_core =
+ "#version 150 core\n\
+ out vec4 fragColor; \n\
+ uniform float globalOpacity; \n\
+ vec4 srcPixel(); \n\
+ vec4 applyMask(vec4); \n\
+ void main() \n\
+ { \n\
+ fragColor = applyMask(srcPixel()*globalOpacity); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_M_core =
+ "#version 150 core\n\
+ out vec4 fragColor; \n\
+ vec4 srcPixel(); \n\
+ vec4 applyMask(vec4); \n\
+ void main() \n\
+ { \n\
+ fragColor = applyMask(srcPixel()); \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_O_core =
+ "#version 150 core\n\
+ out vec4 fragColor; \n\
+ uniform float globalOpacity; \n\
+ vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ fragColor = srcPixel()*globalOpacity; \n\
+ }\n";
+
+static const char* const qopenglslMainFragmentShader_core =
+ "#version 150 core\n\
+ out vec4 fragColor; \n\
+ vec4 srcPixel(); \n\
+ void main() \n\
+ { \n\
+ fragColor = srcPixel(); \n\
+ }\n";
+
+static const char* const qopenglslMaskFragmentShader_core = "\n\
+ in vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ vec4 applyMask(vec4 src) \n\
+ {\n\
+ vec4 mask = texture(maskTexture, textureCoords); \n\
+ return src * mask.r; \n\
+ }\n";
+
+// For source over with subpixel antialiasing, the final color is calculated per component as follows
+// (.a is alpha component, .c is red, green or blue component):
+// alpha = src.a * mask.c * opacity
+// dest.c = dest.c * (1 - alpha) + src.c * alpha
+//
+// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
+// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
+//
+// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
+
+// For source composition with subpixel antialiasing, the final color is calculated per component as follows:
+// alpha = src.a * mask.c * opacity
+// dest.c = dest.c * (1 - mask.c) + src.c * alpha
+//
+
+static const char* const qopenglslRgbMaskFragmentShaderPass1_core = "\n\
+ in vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ vec4 applyMask(vec4 src) \n\
+ { \n\
+ vec4 mask = texture(maskTexture, textureCoords); \n\
+ return src.a * mask; \n\
+ }\n";
+
+static const char* const qopenglslRgbMaskFragmentShaderPass2_core = "\n\
+ in vec2 textureCoords;\n\
+ uniform sampler2D maskTexture;\n\
+ vec4 applyMask(vec4 src) \n\
+ { \n\
+ vec4 mask = texture(maskTexture, textureCoords); \n\
+ return src * mask; \n\
+ }\n";
+
+/*
+ Left to implement:
+ RgbMaskFragmentShader_core,
+ RgbMaskWithGammaFragmentShader_core,
+*/
+
+QT_END_NAMESPACE
+
+#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/qopenglgradientcache.cpp
index fc5e236ca6..7a932a19bb 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ b/src/opengl/qopenglgradientcache.cpp
@@ -37,20 +37,27 @@
**
****************************************************************************/
-#include "qglgradientcache_p.h"
+#include "qopenglgradientcache_p.h"
#include <private/qdrawhelper_p.h>
-#include <private/qgl_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qrgba64_p.h>
#include <QtCore/qmutex.h>
#include <QtCore/qrandom.h>
+#include "qopenglfunctions.h"
+#include <private/qopenglextensions_p.h>
+
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
QT_BEGIN_NAMESPACE
-class QGL2GradientCacheWrapper
+class QOpenGL2GradientCacheWrapper
{
public:
- QGL2GradientCache *cacheForContext(const QGLContext *context) {
+ QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context) {
QMutexLocker lock(&m_mutex);
- return m_resource.value<QGL2GradientCache>(context->contextHandle());
+ return m_resource.value<QOpenGL2GradientCache>(context);
}
private:
@@ -58,39 +65,39 @@ private:
QMutex m_mutex;
};
-Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches)
+Q_GLOBAL_STATIC(QOpenGL2GradientCacheWrapper, qt_gradient_caches)
-QGL2GradientCache::QGL2GradientCache(QOpenGLContext *ctx)
+QOpenGL2GradientCache::QOpenGL2GradientCache(QOpenGLContext *ctx)
: QOpenGLSharedResource(ctx->shareGroup())
{
}
-QGL2GradientCache::~QGL2GradientCache()
+QOpenGL2GradientCache::~QOpenGL2GradientCache()
{
cache.clear();
}
-QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context)
+QOpenGL2GradientCache *QOpenGL2GradientCache::cacheForContext(QOpenGLContext *context)
{
return qt_gradient_caches()->cacheForContext(context);
}
-void QGL2GradientCache::invalidateResource()
+void QOpenGL2GradientCache::invalidateResource()
{
QMutexLocker lock(&m_mutex);
cache.clear();
}
-void QGL2GradientCache::freeResource(QOpenGLContext *)
+void QOpenGL2GradientCache::freeResource(QOpenGLContext *)
{
cleanCache();
}
-void QGL2GradientCache::cleanCache()
+void QOpenGL2GradientCache::cleanCache()
{
- QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
QMutexLocker lock(&m_mutex);
- QGLGradientColorTableHash::const_iterator it = cache.constBegin();
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin();
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
for (; it != cache.constEnd(); ++it) {
const CacheInfo &cache_info = it.value();
funcs->glDeleteTextures(1, &cache_info.texId);
@@ -98,16 +105,16 @@ void QGL2GradientCache::cleanCache()
cache.clear();
}
-GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
+GLuint QOpenGL2GradientCache::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);
+ const QMutexLocker lock(&m_mutex);
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
if (it == cache.constEnd())
return addCacheElement(hash_val, gradient, opacity);
@@ -127,7 +134,7 @@ GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
}
-GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
+GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
{
QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
if (cache.size() == maxCacheSize()) {
@@ -135,7 +142,7 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra
quint64 key = cache.keys()[elem_to_remove];
// need to call glDeleteTextures on each removed cache entry:
- QGLGradientColorTableHash::const_iterator it = cache.constFind(key);
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key);
do {
funcs->glDeleteTextures(1, &it.value().texId);
} while (++it != cache.constEnd() && it.key() == key);
@@ -143,37 +150,81 @@ GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gra
}
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);
+ if (static_cast<QOpenGLExtensions *>(funcs)->hasOpenGLExtension(QOpenGLExtensions::Sized16Formats)) {
+ QRgba64 buffer[1024];
+ generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, paletteSize(), 1,
+ 0, GL_RGBA, GL_UNSIGNED_SHORT, buffer);
+ } else {
+ uint buffer[1024];
+ generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ }
return cache.insert(hash_val, cache_entry).value().texId;
}
-// 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)
+//TODO: Let GL generate the texture using an FBO
+void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, QRgba64 *colorTable, int size, qreal opacity) const
{
- 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;
+ int pos = 0;
+ const QGradientStops s = gradient.stops();
+
+ bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
+
+ uint alpha = qRound(opacity * 256);
+ QRgba64 current_color = combineAlpha256(s[0].second.rgba64(), alpha);
+ qreal incr = 1.0 / qreal(size);
+ qreal fpos = 1.5 * incr;
+ colorTable[pos++] = qPremultiply(current_color);
+
+ while (fpos <= s.first().first) {
+ colorTable[pos] = colorTable[pos - 1];
+ pos++;
+ fpos += incr;
+ }
+
+ if (colorInterpolation)
+ current_color = qPremultiply(current_color);
+
+ const int sLast = s.size() - 1;
+ for (int i = 0; i < sLast; ++i) {
+ qreal delta = 1/(s[i+1].first - s[i].first);
+ QRgba64 next_color = combineAlpha256(s[i + 1].second.rgba64(), alpha);
+ if (colorInterpolation)
+ next_color = qPremultiply(next_color);
+
+ while (fpos < s[i+1].first && pos < size) {
+ int dist = int(256 * ((fpos - s[i].first) * delta));
+ int idist = 256 - dist;
+ if (colorInterpolation)
+ colorTable[pos] = interpolate256(current_color, idist, next_color, dist);
+ else
+ colorTable[pos] = qPremultiply(interpolate256(current_color, idist, next_color, dist));
+ ++pos;
+ fpos += incr;
+ }
+ current_color = next_color;
+ }
+
+ Q_ASSERT(s.size() > 0);
+
+ QRgba64 last_color = qPremultiply(combineAlpha256(s[sLast].second.rgba64(), alpha));
+ for (;pos < size; ++pos)
+ colorTable[pos] = last_color;
+
+ // Make sure the last color stop is represented at the end of the table
+ colorTable[size-1] = last_color;
}
-//TODO: Let GL generate the texture using an FBO
-void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
+void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
{
int pos = 0;
const QGradientStops s = gradient.stops();
+
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
uint alpha = qRound(opacity * 256);
@@ -181,7 +232,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
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));
+ colorTable[pos++] = ARGB2RGBA(qPremultiply(current_color));
while (fpos <= s.first().first) {
colorTable[pos] = colorTable[pos - 1];
@@ -203,9 +254,9 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
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));
+ colorTable[pos] = ARGB2RGBA(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
else
- colorTable[pos] = qtToGlColor(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ colorTable[pos] = ARGB2RGBA(qPremultiply(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
++pos;
fpos += incr;
}
@@ -214,7 +265,7 @@ void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, ui
Q_ASSERT(s.size() > 0);
- uint last_color = qtToGlColor(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha)));
+ uint last_color = ARGB2RGBA(qPremultiply(ARGB_COMBINE_ALPHA(s[sLast].second.rgba(), alpha)));
for (;pos < size; ++pos)
colorTable[pos] = last_color;
diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/qopenglgradientcache_p.h
index 3c9da982e9..da070ae233 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache_p.h
+++ b/src/opengl/qopenglgradientcache_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QGLGRADIENTCACHE_P_H
-#define QGLGRADIENTCACHE_P_H
+#ifndef QOPENGLGRADIENTCACHE_P_H
+#define QOPENGLGRADIENTCACHE_P_H
//
// W A R N I N G
@@ -53,18 +53,19 @@
#include <QMultiHash>
#include <QObject>
-#include <QtOpenGL/QtOpenGL>
-#include <private/qgl_p.h>
+#include <private/qopenglcontext_p.h>
#include <QtCore/qmutex.h>
+#include <QGradient>
+#include <qrgba64.h>
QT_BEGIN_NAMESPACE
-class QGL2GradientCache : public QOpenGLSharedResource
+class QOpenGL2GradientCache : public QOpenGLSharedResource
{
struct CacheInfo
{
inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) :
- stops(s), opacity(op), interpolationMode(mode) {}
+ stops(std::move(s)), opacity(op), interpolationMode(mode) {}
GLuint texId;
QGradientStops stops;
@@ -72,13 +73,13 @@ class QGL2GradientCache : public QOpenGLSharedResource
QGradient::InterpolationMode interpolationMode;
};
- typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash;
+ typedef QMultiHash<quint64, CacheInfo> QOpenGLGradientColorTableHash;
public:
- static QGL2GradientCache *cacheForContext(const QGLContext *context);
+ static QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context);
- QGL2GradientCache(QOpenGLContext *);
- ~QGL2GradientCache();
+ QOpenGL2GradientCache(QOpenGLContext *);
+ ~QOpenGL2GradientCache();
GLuint getBuffer(const QGradient &gradient, qreal opacity);
inline int paletteSize() const { return 1024; }
@@ -89,15 +90,18 @@ public:
private:
inline int maxCacheSize() const { return 60; }
inline void generateGradientColorTable(const QGradient& gradient,
+ QRgba64 *colorTable,
+ int size, qreal opacity) const;
+ inline void generateGradientColorTable(const QGradient& gradient,
uint *colorTable,
int size, qreal opacity) const;
GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity);
void cleanCache();
- QGLGradientColorTableHash cache;
+ QOpenGLGradientColorTableHash cache;
QMutex m_mutex;
};
QT_END_NAMESPACE
-#endif // QGLGRADIENTCACHE_P_H
+#endif // QOPENGLGRADIENTCACHE_P_H
diff --git a/src/opengl/qopenglpaintdevice.cpp b/src/opengl/qopenglpaintdevice.cpp
new file mode 100644
index 0000000000..811425cf69
--- /dev/null
+++ b/src/opengl/qopenglpaintdevice.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** 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 <qopenglpaintdevice.h>
+#include <qpaintengine.h>
+#include <qthreadstorage.h>
+
+#include <private/qopenglpaintdevice_p.h>
+#include <private/qobject_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglframebufferobject_p.h>
+#include <private/qopenglpaintengine_p.h>
+
+// for qt_defaultDpiX/Y
+#include <private/qfont_p.h>
+
+#include <qopenglfunctions.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLPaintDevice
+ \brief The QOpenGLPaintDevice class enables painting to an OpenGL context using QPainter.
+ \since 5.0
+ \inmodule QtOpenGL
+
+ \ingroup painting-3D
+
+ The QOpenGLPaintDevice uses the \b current QOpenGL context to render
+ QPainter draw commands. The context is captured upon construction. It
+ requires support for OpenGL (ES) 2.0 or higher.
+
+ \section1 Performance
+
+ The QOpenGLPaintDevice is almost always hardware accelerated and
+ has the potential of being much faster than software
+ rasterization. However, it is more sensitive to state changes, and
+ therefore requires the drawing commands to be carefully ordered to
+ achieve optimal performance.
+
+ \section1 Antialiasing and Quality
+
+ Antialiasing in the OpenGL paint engine is done using
+ multisampling. Most hardware require significantly more memory to
+ do multisampling and the resulting quality is not on par with the
+ quality of the software paint engine. The OpenGL paint engine's
+ strength lies in its performance, not its visual rendering
+ quality.
+
+ \section1 State Changes
+
+ When painting to a QOpenGLPaintDevice using QPainter, the state of
+ the current OpenGL context will be altered by the paint engine to
+ reflect its needs. Applications should not rely upon the OpenGL
+ state being reset to its original conditions, particularly the
+ current shader program, OpenGL viewport, texture units, and
+ drawing modes.
+
+ \section1 Mixing QPainter and OpenGL
+
+ When intermixing QPainter and OpenGL, it is important to notify
+ QPainter that the OpenGL state may have been cluttered so it can
+ restore its internal state. This is achieved by calling \l
+ QPainter::beginNativePainting() before starting the OpenGL
+ rendering and calling \l QPainter::endNativePainting() after
+ finishing.
+
+ \sa {OpenGL Window Example}
+
+*/
+
+/*!
+ Constructs a QOpenGLPaintDevice.
+
+ The QOpenGLPaintDevice is only valid for the current context.
+
+ \sa QOpenGLContext::currentContext()
+*/
+QOpenGLPaintDevice::QOpenGLPaintDevice()
+ : d_ptr(new QOpenGLPaintDevicePrivate(QSize()))
+{
+}
+
+/*!
+ Constructs a QOpenGLPaintDevice with the given \a size.
+
+ The QOpenGLPaintDevice is only valid for the current context.
+
+ \sa QOpenGLContext::currentContext()
+*/
+QOpenGLPaintDevice::QOpenGLPaintDevice(const QSize &size)
+ : d_ptr(new QOpenGLPaintDevicePrivate(size))
+{
+}
+
+/*!
+ Constructs a QOpenGLPaintDevice with the given \a width and \a height.
+
+ The QOpenGLPaintDevice is only valid for the current context.
+
+ \sa QOpenGLContext::currentContext()
+*/
+QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height)
+ : QOpenGLPaintDevice(QSize(width, height))
+{
+}
+
+/*!
+ \internal
+ */
+QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd)
+ : d_ptr(&dd)
+{
+}
+
+/*!
+ Destroys the QOpenGLPaintDevice.
+*/
+
+QOpenGLPaintDevice::~QOpenGLPaintDevice()
+{
+ delete d_ptr->engine;
+}
+
+/*!
+ \fn int QOpenGLPaintDevice::devType() const
+ \internal
+ \reimp
+*/
+
+QOpenGLPaintDevicePrivate::QOpenGLPaintDevicePrivate(const QSize &sz)
+ : size(sz)
+ , ctx(QOpenGLContext::currentContext())
+ , dpmx(qt_defaultDpiX() * 100. / 2.54)
+ , dpmy(qt_defaultDpiY() * 100. / 2.54)
+ , devicePixelRatio(1.0)
+ , flipped(false)
+ , engine(nullptr)
+{
+}
+
+QOpenGLPaintDevicePrivate::~QOpenGLPaintDevicePrivate()
+{
+}
+
+class QOpenGLEngineThreadStorage
+{
+public:
+ QPaintEngine *engine() {
+ QPaintEngine *&localEngine = storage.localData();
+ if (!localEngine)
+ localEngine = new QOpenGL2PaintEngineEx;
+ return localEngine;
+ }
+
+private:
+ QThreadStorage<QPaintEngine *> storage;
+};
+
+Q_GLOBAL_STATIC(QOpenGLEngineThreadStorage, qt_opengl_engine)
+
+/*!
+ \reimp
+*/
+
+QPaintEngine *QOpenGLPaintDevice::paintEngine() const
+{
+ if (d_ptr->engine)
+ return d_ptr->engine;
+
+ QPaintEngine *engine = qt_opengl_engine()->engine();
+ if (engine->isActive() && engine->paintDevice() != this) {
+ d_ptr->engine = new QOpenGL2PaintEngineEx;
+ return d_ptr->engine;
+ }
+
+ return engine;
+}
+
+/*!
+ Returns the OpenGL context associated with the paint device.
+*/
+
+QOpenGLContext *QOpenGLPaintDevice::context() const
+{
+ return d_ptr->ctx;
+}
+
+/*!
+ Returns the pixel size of the paint device.
+
+ \sa setSize()
+*/
+
+QSize QOpenGLPaintDevice::size() const
+{
+ return d_ptr->size;
+}
+
+/*!
+ Sets the pixel size of the paint device to \a size.
+
+ \sa size()
+*/
+
+void QOpenGLPaintDevice::setSize(const QSize &size)
+{
+ d_ptr->size = size;
+}
+
+/*!
+ Sets the device pixel ratio for the paint device to \a devicePixelRatio.
+*/
+void QOpenGLPaintDevice::setDevicePixelRatio(qreal devicePixelRatio)
+{
+ d_ptr->devicePixelRatio = devicePixelRatio;
+}
+
+/*!
+ \reimp
+*/
+
+int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case PdmWidth:
+ return d_ptr->size.width();
+ case PdmHeight:
+ return d_ptr->size.height();
+ case PdmDepth:
+ return 32;
+ case PdmWidthMM:
+ return qRound(d_ptr->size.width() * 1000 / d_ptr->dpmx);
+ case PdmHeightMM:
+ return qRound(d_ptr->size.height() * 1000 / d_ptr->dpmy);
+ case PdmNumColors:
+ return 0;
+ case PdmDpiX:
+ return qRound(d_ptr->dpmx * 0.0254);
+ case PdmDpiY:
+ return qRound(d_ptr->dpmy * 0.0254);
+ case PdmPhysicalDpiX:
+ return qRound(d_ptr->dpmx * 0.0254);
+ case PdmPhysicalDpiY:
+ return qRound(d_ptr->dpmy * 0.0254);
+ case PdmDevicePixelRatio:
+ return d_ptr->devicePixelRatio;
+ case PdmDevicePixelRatioScaled:
+ return d_ptr->devicePixelRatio * QPaintDevice::devicePixelRatioFScale();
+
+ default:
+ qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
+ return 0;
+ }
+}
+
+/*!
+ Returns the number of pixels per meter horizontally.
+
+ \sa setDotsPerMeterX()
+*/
+
+qreal QOpenGLPaintDevice::dotsPerMeterX() const
+{
+ return d_ptr->dpmx;
+}
+
+/*!
+ Returns the number of pixels per meter vertically.
+
+ \sa setDotsPerMeterY()
+*/
+
+qreal QOpenGLPaintDevice::dotsPerMeterY() const
+{
+ return d_ptr->dpmy;
+}
+
+/*!
+ Sets the number of pixels per meter horizontally to \a dpmx.
+
+ \sa dotsPerMeterX()
+*/
+
+void QOpenGLPaintDevice::setDotsPerMeterX(qreal dpmx)
+{
+ d_ptr->dpmx = dpmx;
+}
+
+/*!
+ Sets the number of pixels per meter vertically to \a dpmy.
+
+ \sa dotsPerMeterY()
+*/
+
+void QOpenGLPaintDevice::setDotsPerMeterY(qreal dpmy)
+{
+ d_ptr->dpmx = dpmy;
+}
+
+/*!
+ Sets whether painting should be flipped around the Y-axis or not to \a flipped.
+
+ \sa paintFlipped()
+*/
+void QOpenGLPaintDevice::setPaintFlipped(bool flipped)
+{
+ d_ptr->flipped = flipped;
+}
+
+/*!
+ Returns \c true if painting is flipped around the Y-axis.
+
+ \sa setPaintFlipped()
+*/
+
+bool QOpenGLPaintDevice::paintFlipped() const
+{
+ return d_ptr->flipped;
+}
+
+/*!
+ This virtual method is provided as a callback to allow re-binding a target
+ frame buffer object or context when different QOpenGLPaintDevice instances
+ are issuing draw calls alternately.
+
+ \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger
+ this method.
+
+ The default implementation does nothing.
+*/
+void QOpenGLPaintDevice::ensureActiveTarget()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopenglpaintdevice.h b/src/opengl/qopenglpaintdevice.h
new file mode 100644
index 0000000000..f4e1ce4a2e
--- /dev/null
+++ b/src/opengl/qopenglpaintdevice.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** 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 QOPENGLPAINTDEVICE_H
+#define QOPENGLPAINTDEVICE_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#ifndef QT_NO_OPENGL
+
+#include <QtGui/qpaintdevice.h>
+#include <QtGui/qopengl.h>
+#include <QtGui/qopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLPaintDevicePrivate;
+
+class Q_OPENGL_EXPORT QOpenGLPaintDevice : public QPaintDevice
+{
+ Q_DECLARE_PRIVATE(QOpenGLPaintDevice)
+public:
+ QOpenGLPaintDevice();
+ explicit QOpenGLPaintDevice(const QSize &size);
+ QOpenGLPaintDevice(int width, int height);
+ ~QOpenGLPaintDevice();
+
+ int devType() const override { return QInternal::OpenGL; }
+ QPaintEngine *paintEngine() const override;
+
+ QOpenGLContext *context() const;
+ QSize size() const;
+ void setSize(const QSize &size);
+ void setDevicePixelRatio(qreal devicePixelRatio);
+
+ qreal dotsPerMeterX() const;
+ qreal dotsPerMeterY() const;
+
+ void setDotsPerMeterX(qreal);
+ void setDotsPerMeterY(qreal);
+
+ void setPaintFlipped(bool flipped);
+ bool paintFlipped() const;
+
+ virtual void ensureActiveTarget();
+
+protected:
+ QOpenGLPaintDevice(QOpenGLPaintDevicePrivate &dd);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+
+ Q_DISABLE_COPY(QOpenGLPaintDevice)
+ QScopedPointer<QOpenGLPaintDevicePrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLPAINTDEVICE_H
diff --git a/src/opengl/qopenglpaintdevice_p.h b/src/opengl/qopenglpaintdevice_p.h
new file mode 100644
index 0000000000..f4f02e7b57
--- /dev/null
+++ b/src/opengl/qopenglpaintdevice_p.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 QOPENGL_PAINTDEVICE_P_H
+#define QOPENGL_PAINTDEVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Qt OpenGL classes. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qopenglpaintdevice.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QPaintEngine;
+
+class Q_OPENGL_EXPORT QOpenGLPaintDevicePrivate
+{
+public:
+ QOpenGLPaintDevicePrivate(const QSize &size);
+ virtual ~QOpenGLPaintDevicePrivate();
+
+ static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); }
+
+ virtual void beginPaint() { }
+ virtual void endPaint() { }
+
+public:
+ QSize size;
+ QOpenGLContext *ctx;
+
+ qreal dpmx;
+ qreal dpmy;
+ qreal devicePixelRatio;
+
+ bool flipped;
+
+ QPaintEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENGL_PAINTDEVICE_P_H
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/qopenglpaintengine.cpp
index 2546f6dc13..4168067e8f 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/qopenglpaintengine.cpp
@@ -62,76 +62,74 @@
// #define QT_OPENGL_CACHE_AS_VBOS
-#include "qglgradientcache_p.h"
-#include "qpaintengineex_opengl2_p.h"
+#include <private/qopenglgradientcache_p.h>
+#include <private/qopengltexturecache_p.h>
+#include "qopenglpaintengine_p.h"
+#include "qopenglpaintdevice_p.h"
#include <string.h> //for memcpy
#include <qmath.h>
-#include <private/qgl_p.h>
+#include <private/qopengl_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
#include <private/qpaintengineex_p.h>
#include <QPaintEngine>
#include <private/qpainter_p.h>
#include <private/qfontengine_p.h>
#include <private/qdatabuffer_p.h>
#include <private/qstatictext_p.h>
-#include <QtGui/private/qtriangulator_p.h>
+#include <private/qtriangulator_p.h>
-#include "qglengineshadermanager_p.h"
-#include "qgl2pexvertexarray_p.h"
-#include "qtextureglyphcache_gl_p.h"
+#include <private/qopenglengineshadermanager_p.h>
+#include <private/qopengl2pexvertexarray_p.h>
+#include <private/qopengltextureglyphcache_p.h>
#include <QDebug>
-#ifndef QT_OPENGL_ES_2
-# include <qopenglfunctions_1_1.h>
-#endif
+#ifndef GL_KHR_blend_equation_advanced
+#define GL_KHR_blend_equation_advanced 1
+#define GL_MULTIPLY_KHR 0x9294
+#define GL_SCREEN_KHR 0x9295
+#define GL_OVERLAY_KHR 0x9296
+#define GL_DARKEN_KHR 0x9297
+#define GL_LIGHTEN_KHR 0x9298
+#define GL_COLORDODGE_KHR 0x9299
+#define GL_COLORBURN_KHR 0x929A
+#define GL_HARDLIGHT_KHR 0x929B
+#define GL_SOFTLIGHT_KHR 0x929C
+#define GL_DIFFERENCE_KHR 0x929E
+#define GL_EXCLUSION_KHR 0x92A0
+#endif /* GL_KHR_blend_equation_advanced */
+
+#ifndef GL_KHR_blend_equation_advanced_coherent
+#define GL_KHR_blend_equation_advanced_coherent 1
+#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285
+#endif /* GL_KHR_blend_equation_advanced_coherent */
QT_BEGIN_NAMESPACE
-
-Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
+Q_OPENGL_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert);
////////////////////////////////// Private Methods //////////////////////////////////////////
-QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
+QOpenGL2PaintEngineExPrivate::~QOpenGL2PaintEngineExPrivate()
{
delete shaderManager;
- while (pathCaches.size()) {
- QVectorPath::CacheEntry *e = *(pathCaches.constBegin());
- e->cleanup(e->engine, e->data);
- e->data = 0;
- e->engine = 0;
- }
+ vertexBuffer.destroy();
+ texCoordBuffer.destroy();
+ opacityBuffer.destroy();
+ indexBuffer.destroy();
+ vao.destroy();
if (elementIndicesVBOId != 0) {
- glDeleteBuffers(1, &elementIndicesVBOId);
+ funcs.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;
@@ -143,7 +141,7 @@ inline QColor qt_premultiplyColor(QColor c, GLfloat opacity)
}
-void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
+void QOpenGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
{
if (qbrush_fast_equals(currentBrush, brush))
return;
@@ -152,8 +150,8 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
Q_ASSERT(newStyle != Qt::NoBrush);
currentBrush = brush;
- if (!currentBrushPixmap.isNull())
- currentBrushPixmap = QPixmap();
+ if (!currentBrushImage.isNull())
+ currentBrushImage = QImage();
brushUniformsDirty = true; // All brushes have at least one uniform
if (newStyle > Qt::SolidPattern)
@@ -162,7 +160,7 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
if (currentBrush.style() == Qt::TexturePattern
&& qHasPixmapTexture(brush) && brush.texture().isQBitmap())
{
- shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
+ shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::TextureSrcWithPattern);
} else {
shaderManager->setSrcPixelType(newStyle);
}
@@ -170,7 +168,7 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush& brush)
}
-void QGL2PaintEngineExPrivate::useSimpleShader()
+void QOpenGL2PaintEngineExPrivate::useSimpleShader()
{
shaderManager->useSimpleProgram();
@@ -178,74 +176,162 @@ void QGL2PaintEngineExPrivate::useSimpleShader()
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
+/*
+ Single entry-point for activating, binding, and setting properties.
+
+ Allows keeping track of (caching) the latest texture unit and bound
+ texture in a central place, so that we can skip re-binding unless
+ needed.
+
+ \note Any code or Qt API that internally activates or binds will
+ not affect the cache used by this function, which means they will
+ lead to inconsisent state. QPainter::beginNativePainting() takes
+ care of resetting the cache, so for user–code this is fine, but
+ internally in the paint engine care must be taken to not call
+ functions that may activate or bind under our feet.
+*/
+template<typename T>
+void QOpenGL2PaintEngineExPrivate::updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode)
+{
+ static const GLenum target = GL_TEXTURE_2D;
-void QGL2PaintEngineExPrivate::updateBrushTexture()
+ activateTextureUnit(textureUnit);
+
+ GLuint textureId = bindTexture(texture);
+
+ if (updateMode == UpdateIfNeeded && textureId == lastTextureUsed)
+ return;
+
+ lastTextureUsed = textureId;
+
+ funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode);
+ funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode);
+
+ funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filterMode);
+ funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filterMode);
+}
+
+void QOpenGL2PaintEngineExPrivate::activateTextureUnit(GLenum textureUnit)
{
- Q_Q(QGL2PaintEngineEx);
-// qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()");
+ if (textureUnit != lastTextureUnitUsed) {
+ funcs.glActiveTexture(GL_TEXTURE0 + textureUnit);
+ lastTextureUnitUsed = textureUnit;
+
+ // We simplify things by keeping a single cached value of the last
+ // texture that was bound, instead of one per texture unit. This
+ // means that switching texture units could potentially mean we
+ // need a re-bind and corresponding parameter updates.
+ lastTextureUsed = GLuint(-1);
+ }
+}
+
+template<>
+GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const GLuint &textureId)
+{
+ if (textureId != lastTextureUsed)
+ funcs.glBindTexture(GL_TEXTURE_2D, textureId);
+
+ return textureId;
+}
+
+template<>
+GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QImage &image)
+{
+ return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, image);
+}
+
+template<>
+GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QPixmap &pixmap)
+{
+ return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, pixmap);
+}
+
+template<>
+GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const QGradient &gradient)
+{
+ // We apply global opacity in the fragment shaders, so we always pass 1.0
+ // for opacity to the cache.
+ GLuint textureId = QOpenGL2GradientCache::cacheForContext(ctx)->getBuffer(gradient, 1.0);
+
+ // QOpenGL2GradientCache::getBuffer() may bind and generate a new texture if it
+ // hasn't been cached yet, but will otherwise return an unbound texture id. To
+ // be sure that the texture is bound, we unfortunately have to bind again,
+ // which results in the initial generation of the texture doing two binds.
+ return bindTexture(textureId);
+}
+
+struct ImageWithBindOptions
+{
+ const QImage &image;
+ QOpenGLTextureUploader::BindOptions options;
+};
+
+template<>
+GLuint QOpenGL2PaintEngineExPrivate::bindTexture(const ImageWithBindOptions &imageWithOptions)
+{
+ return QOpenGLTextureCache::cacheForContext(ctx)->bindTexture(ctx, imageWithOptions.image, imageWithOptions.options);
+}
+
+inline static bool isPowerOfTwo(int x)
+{
+ // Assumption: x >= 1
+ return x == (x & -x);
+}
+
+void QOpenGL2PaintEngineExPrivate::updateBrushTexture()
+{
+ Q_Q(QOpenGL2PaintEngineEx);
+// qDebug("QOpenGL2PaintEngineExPrivate::updateBrushTexture()");
Qt::BrushStyle style = currentBrush.style();
+ bool smoothPixmapTransform = q->state()->renderHints & QPainter::SmoothPixmapTransform;
+ GLenum filterMode = smoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
+
if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
// Get the image data for the pattern
- QImage texImage = qt_imageForBrush(style, false);
+ QImage textureImage = 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);
+ updateTexture(QT_BRUSH_TEXTURE_UNIT, textureImage, GL_REPEAT, filterMode, ForceUpdate);
}
else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
// Gradiant brush: All the gradiants use the same texture
- const QGradient* g = currentBrush.gradient();
+ const QGradient *gradient = 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);
+ GLenum wrapMode = GL_CLAMP_TO_EDGE;
+ if (gradient->spread() == QGradient::RepeatSpread || gradient->type() == QGradient::ConicalGradient)
+ wrapMode = GL_REPEAT;
+ else if (gradient->spread() == QGradient::ReflectSpread)
+ wrapMode = GL_MIRRORED_REPEAT;
- 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);
+ updateTexture(QT_BRUSH_TEXTURE_UNIT, *gradient, wrapMode, filterMode, ForceUpdate);
}
else if (style == Qt::TexturePattern) {
- currentBrushPixmap = currentBrush.texture();
+ currentBrushImage = currentBrush.textureImage();
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);
+ QSize newSize = currentBrushImage.size();
+ newSize = newSize.boundedTo(QSize(max_texture_size, max_texture_size));
+ if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextureRepeat)) {
+ if (!isPowerOfTwo(newSize.width()) || !isPowerOfTwo(newSize.height())) {
+ newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
+ newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
+ }
+ }
+ if (currentBrushImage.size() != newSize)
+ currentBrushImage = currentBrushImage.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
GLuint wrapMode = GL_REPEAT;
- 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;
+ updateTexture(QT_BRUSH_TEXTURE_UNIT, currentBrushImage, wrapMode, filterMode, ForceUpdate);
}
brushTextureDirty = false;
}
-void QGL2PaintEngineExPrivate::updateBrushUniforms()
+void QOpenGL2PaintEngineExPrivate::updateBrushUniforms()
{
-// qDebug("QGL2PaintEngineExPrivate::updateBrushUniforms()");
+// qDebug("QOpenGL2PaintEngineExPrivate::updateBrushUniforms()");
Qt::BrushStyle style = currentBrush.style();
if (style == Qt::NoBrush)
@@ -255,7 +341,7 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style == Qt::SolidPattern) {
QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::FragmentColor), col);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::FragmentColor), col);
}
else {
// All other brushes have a transform and thus need the translation point:
@@ -264,10 +350,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style <= Qt::DiagCrossPattern) {
QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
}
else if (style == Qt::LinearGradientPattern) {
const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush.gradient());
@@ -284,10 +370,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
1.0f / (l.x() * l.x() + l.y() * l.y())
);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::LinearData), linearData);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::LinearData), linearData);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
}
else if (style == Qt::ConicalGradientPattern) {
const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush.gradient());
@@ -295,10 +381,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
GLfloat angle = -qDegreesToRadians(g->angle());
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Angle), angle);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Angle), angle);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
}
else if (style == Qt::RadialGradientPattern) {
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush.gradient());
@@ -308,38 +394,38 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp), fmp);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Fmp), fmp);
GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Inverse2Fmp2MRadius2),
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Fmp2MRadius2), fmp2_m_radius2);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::Inverse2Fmp2MRadius2),
GLfloat(1.0 / (2.0*fmp2_m_radius2)));
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::SqrFr),
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::SqrFr),
GLfloat(g->focalRadius() * g->focalRadius()));
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::BRadius),
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BRadius),
GLfloat(2 * (g->centerRadius() - g->focalRadius()) * g->focalRadius()),
g->focalRadius(),
g->centerRadius() - g->focalRadius());
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
}
else if (style == Qt::TexturePattern) {
const QPixmap& texPixmap = currentBrush.texture();
if (qHasPixmapTexture(currentBrush) && currentBrush.texture().isQBitmap()) {
QColor col = qt_premultiplyColor(currentBrush.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col);
}
QSizeF invertedTextureSize(1.0 / texPixmap.width(), 1.0 / texPixmap.height());
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::InvertedTextureSize), invertedTextureSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::InvertedTextureSize), invertedTextureSize);
QVector2D halfViewportSize(width*0.5, height*0.5);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::HalfViewportSize), halfViewportSize);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::HalfViewportSize), halfViewportSize);
}
else
- qWarning("QGL2PaintEngineEx: Unimplemented fill style");
+ qWarning("QOpenGL2PaintEngineEx: Unimplemented fill style");
const QPointF &brushOrigin = q->state()->brushOrigin;
QTransform matrix = q->state()->matrix;
@@ -348,28 +434,24 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QTransform translate(1, 0, 0, 1, -translationPoint.x(), -translationPoint.y());
qreal m22 = -1;
qreal dy = height;
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
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;
+ QTransform 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);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTransform), inv_matrix);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::BrushTexture), QT_BRUSH_TEXTURE_UNIT);
}
brushUniformsDirty = false;
}
// This assumes the shader manager has already setup the correct shader program
-void QGL2PaintEngineExPrivate::updateMatrix()
+void QOpenGL2PaintEngineExPrivate::updateMatrix()
{
-// qDebug("QGL2PaintEngineExPrivate::updateMatrix()");
+// qDebug("QOpenGL2PaintEngineExPrivate::updateMatrix()");
const QTransform& transform = q->state()->matrix;
@@ -396,7 +478,7 @@ void QGL2PaintEngineExPrivate::updateMatrix()
GLfloat dx = transform.dx();
GLfloat dy = transform.dy();
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
hfactor *= -1;
dy -= height;
}
@@ -429,59 +511,107 @@ void QGL2PaintEngineExPrivate::updateMatrix()
// 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]);
+ funcs.glVertexAttrib3fv(QT_PMV_MATRIX_1_ATTR, pmvMatrix[0]);
+ funcs.glVertexAttrib3fv(QT_PMV_MATRIX_2_ATTR, pmvMatrix[1]);
+ funcs.glVertexAttrib3fv(QT_PMV_MATRIX_3_ATTR, pmvMatrix[2]);
dasher.setInvScale(inverseScale);
stroker.setInvScale(inverseScale);
}
-void QGL2PaintEngineExPrivate::updateCompositionMode()
+void QOpenGL2PaintEngineExPrivate::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;
+// qDebug() << "QOpenGL2PaintEngineExPrivate::updateCompositionMode() - Setting GL composition mode for " << q->state()->composition_mode;
+ if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::BlendEquationAdvanced)) {
+ if (q->state()->composition_mode <= QPainter::CompositionMode_Plus) {
+ funcs.glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
+ funcs.glBlendEquation(GL_FUNC_ADD);
+ } else {
+ funcs.glEnable(GL_BLEND_ADVANCED_COHERENT_KHR);
+ }
+ shaderManager->setCompositionMode(q->state()->composition_mode);
+ } else {
+ if (q->state()->composition_mode > QPainter::CompositionMode_Plus) {
+ qWarning("Unsupported composition mode");
+ compositionModeDirty = false;
+ return;
+ }
+ }
switch(q->state()->composition_mode) {
case QPainter::CompositionMode_SourceOver:
- glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+ funcs.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
break;
case QPainter::CompositionMode_DestinationOver:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
+ funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE);
break;
case QPainter::CompositionMode_Clear:
- glBlendFunc(GL_ZERO, GL_ZERO);
+ funcs.glBlendFunc(GL_ZERO, GL_ZERO);
break;
case QPainter::CompositionMode_Source:
- glBlendFunc(GL_ONE, GL_ZERO);
+ funcs.glBlendFunc(GL_ONE, GL_ZERO);
break;
case QPainter::CompositionMode_Destination:
- glBlendFunc(GL_ZERO, GL_ONE);
+ funcs.glBlendFunc(GL_ZERO, GL_ONE);
break;
case QPainter::CompositionMode_SourceIn:
- glBlendFunc(GL_DST_ALPHA, GL_ZERO);
+ funcs.glBlendFunc(GL_DST_ALPHA, GL_ZERO);
break;
case QPainter::CompositionMode_DestinationIn:
- glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
+ funcs.glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
break;
case QPainter::CompositionMode_SourceOut:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
+ funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ZERO);
break;
case QPainter::CompositionMode_DestinationOut:
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+ funcs.glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
break;
case QPainter::CompositionMode_SourceAtop:
- glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ funcs.glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case QPainter::CompositionMode_DestinationAtop:
- glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA);
+ funcs.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);
+ funcs.glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case QPainter::CompositionMode_Plus:
- glBlendFunc(GL_ONE, GL_ONE);
+ funcs.glBlendFunc(GL_ONE, GL_ONE);
+ break;
+ case QPainter::CompositionMode_Multiply:
+ funcs.glBlendEquation(GL_MULTIPLY_KHR);
+ break;
+ case QPainter::CompositionMode_Screen:
+ funcs.glBlendEquation(GL_SCREEN_KHR);
+ break;
+ case QPainter::CompositionMode_Overlay:
+ funcs.glBlendEquation(GL_OVERLAY_KHR);
+ break;
+ case QPainter::CompositionMode_Darken:
+ funcs.glBlendEquation(GL_DARKEN_KHR);
+ break;
+ case QPainter::CompositionMode_Lighten:
+ funcs.glBlendEquation(GL_LIGHTEN_KHR);
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ funcs.glBlendEquation(GL_COLORDODGE_KHR);
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ funcs.glBlendEquation(GL_COLORBURN_KHR);
+ break;
+ case QPainter::CompositionMode_HardLight:
+ funcs.glBlendEquation(GL_HARDLIGHT_KHR);
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ funcs.glBlendEquation(GL_SOFTLIGHT_KHR);
+ break;
+ case QPainter::CompositionMode_Difference:
+ funcs.glBlendEquation(GL_DIFFERENCE_KHR);
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ funcs.glBlendEquation(GL_EXCLUSION_KHR);
break;
default:
qWarning("Unsupported composition mode");
@@ -491,7 +621,7 @@ void QGL2PaintEngineExPrivate::updateCompositionMode()
compositionModeDirty = false;
}
-static inline void setCoords(GLfloat *coords, const QGLRect &rect)
+static inline void setCoords(GLfloat *coords, const QOpenGLRect &rect)
{
coords[0] = rect.left;
coords[1] = rect.top;
@@ -503,11 +633,10 @@ static inline void setCoords(GLfloat *coords, const QGLRect &rect)
coords[7] = rect.bottom;
}
-void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
+void QOpenGL2PaintEngineExPrivate::drawTexture(const QOpenGLRect& dest, const QOpenGLRect& 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;
@@ -515,176 +644,143 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s
}
if (prepareForDraw(opaque))
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
if (pattern) {
QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::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);
+ QOpenGLRect 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);
+ setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
+ setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
+
+ uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8);
+ uploadData(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray, 8);
+
+ funcs.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
-void QGL2PaintEngineEx::beginNativePainting()
+void QOpenGL2PaintEngineEx::beginNativePainting()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
ensureActive();
d->transferMode(BrushDrawingMode);
d->nativePaintingActive = true;
- d->glUseProgram(0);
+ d->funcs.glUseProgram(0);
// Disable all the vertex attribute arrays:
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
- d->glDisableVertexAttribArray(i);
+ d->funcs.glDisableVertexAttribArray(i);
+
+#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC)
+ Q_ASSERT(QOpenGLContext::currentContext());
+ const QOpenGLContext *ctx = d->ctx;
+ const QSurfaceFormat &fmt = d->device->context()->format();
+ if (fmt.majorVersion() < 3 || (fmt.majorVersion() == 3 && fmt.minorVersion() < 1)
+ || (fmt.majorVersion() == 3 && fmt.minorVersion() == 1 && ctx->hasExtension(QByteArrayLiteral("GL_ARB_compatibility")))
+ || fmt.profile() == QSurfaceFormat::CompatibilityProfile)
+ {
+ // be nice to people who mix OpenGL 1.x code with QPainter commands
+ // by setting modelview and projection matrices to mirror the GL 1
+ // paint engine
+ const QTransform& mtx = state()->matrix;
-#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]);
- }
+ float mv_matrix[4][4] =
+ {
+ { float(mtx.m11()), float(mtx.m12()), 0, float(mtx.m13()) },
+ { float(mtx.m21()), float(mtx.m22()), 0, float(mtx.m23()) },
+ { 0, 0, 1, 0 },
+ { float(mtx.dx()), float(mtx.dy()), 0, float(mtx.m33()) }
+ };
+
+ const QSize sz = d->device->size();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(&mv_matrix[0][0]);
}
-#endif
+#endif // QT_OPENGL_ES_2
+ d->resetGLState();
+
+ // We don't know what texture units and textures the native painting
+ // will activate and bind, so we can't assume anything when we return
+ // from the native painting.
+ d->lastTextureUnitUsed = QT_UNKNOWN_TEXTURE_UNIT;
d->lastTextureUsed = GLuint(-1);
+
d->dirtyStencilRegion = QRect(0, 0, d->width, d->height);
- d->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()) {
+void QOpenGL2PaintEngineExPrivate::resetGLState()
+{
+ activateTextureUnit(QT_DEFAULT_TEXTURE_UNIT);
+
+ funcs.glDisable(GL_BLEND);
+ funcs.glDisable(GL_STENCIL_TEST);
+ funcs.glDisable(GL_DEPTH_TEST);
+ funcs.glDisable(GL_SCISSOR_TEST);
+ funcs.glDepthMask(true);
+ funcs.glDepthFunc(GL_LESS);
+ funcs.glClearDepthf(1);
+ funcs.glStencilMask(0xff);
+ funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
+ funcs.glStencilFunc(GL_ALWAYS, 0, 0xff);
+ setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
+ setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, false);
+ setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
// gl_Color, corresponding to vertex attribute 3, may have been changed
float color[] = { 1.0f, 1.0f, 1.0f, 1.0f };
- glVertexAttrib4fv(3, color);
+ funcs.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;
+ if (vao.isCreated()) {
+ vao.release();
+ funcs.glBindBuffer(GL_ARRAY_BUFFER, 0);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
-
- return false;
}
-void QGL2PaintEngineEx::endNativePainting()
+void QOpenGL2PaintEngineEx::endNativePainting()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
d->needsSync = true;
d->nativePaintingActive = false;
}
-void QGL2PaintEngineEx::invalidateState()
+void QOpenGL2PaintEngineEx::invalidateState()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
d->needsSync = true;
}
-bool QGL2PaintEngineEx::isNativePaintingActive() const {
- Q_D(const QGL2PaintEngineEx);
+bool QOpenGL2PaintEngineEx::isNativePaintingActive() const {
+ Q_D(const QOpenGL2PaintEngineEx);
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)
+void QOpenGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
{
if (newMode == mode)
return;
- if (mode == TextDrawingMode || mode == ImageDrawingMode || mode == ImageArrayDrawingMode) {
- lastTextureUsed = GLuint(-1);
- }
-
if (newMode == TextDrawingMode) {
shaderManager->setHasComplexGeometry(true);
} else {
@@ -692,24 +788,26 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
}
if (newMode == ImageDrawingMode) {
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray);
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray);
+ uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8);
+ uploadData(QT_TEXTURE_COORDS_ATTR, staticTextureCoordinateArray, 8);
}
- 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());
+ if (newMode == ImageArrayDrawingMode || newMode == ImageOpacityArrayDrawingMode) {
+ uploadData(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data(), vertexCoordinateArray.vertexCount() * 2);
+ uploadData(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data(), textureCoordinateArray.vertexCount() * 2);
+
+ if (newMode == ImageOpacityArrayDrawingMode)
+ uploadData(QT_OPACITY_ATTR, (GLfloat*)opacityArray.data(), opacityArray.size());
}
// This needs to change when we implement high-quality anti-aliasing...
if (newMode != TextDrawingMode)
- shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
+ shaderManager->setMaskType(QOpenGLEngineShaderManager::NoMask);
mode = newMode;
}
-struct QGL2PEVectorPathCache
+struct QOpenGL2PEVectorPathCache
{
#ifdef QT_OPENGL_CACHE_AS_VBOS
GLuint vbo;
@@ -725,12 +823,12 @@ struct QGL2PEVectorPathCache
QVertexIndexVector::Type indexType;
};
-void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data)
+void QOpenGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *data)
{
- QGL2PEVectorPathCache *c = (QGL2PEVectorPathCache *) data;
+ QOpenGL2PEVectorPathCache *c = (QOpenGL2PEVectorPathCache *) data;
#ifdef QT_OPENGL_CACHE_AS_VBOS
Q_ASSERT(engine->type() == QPaintEngine::OpenGL2);
- static_cast<QGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo;
+ static_cast<QOpenGL2PaintEngineEx *>(engine)->d_func()->unusedVBOSToClean << c->vbo;
if (c->ibo)
d->unusedIBOSToClean << c->ibo;
#else
@@ -742,7 +840,7 @@ void QGL2PaintEngineExPrivate::cleanupVectorPath(QPaintEngineEx *engine, void *d
}
// Assumes everything is configured for the brush you want to use
-void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
+void QOpenGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
transferMode(BrushDrawingMode);
@@ -755,40 +853,40 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
if (matrixDirty)
updateMatrix();
+ const bool supportsElementIndexUint = funcs.hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint);
+
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
// Check to see if there's any hints
if (path.shape() == QVectorPath::RectangleHint) {
- QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
+ QOpenGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
prepareForDraw(currentBrush.isOpaque());
composite(rect);
} else if (path.isConvex()) {
if (path.isCacheable()) {
QVectorPath::CacheEntry *data = path.lookupCacheData(q);
- QGL2PEVectorPathCache *cache;
+ QOpenGL2PEVectorPathCache *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) {
+ cache = (QOpenGL2PEVectorPathCache *) data->data;
+ // Check if scale factor is exceeded and regenerate if so...
+ qreal scaleFactor = cache->iscale / inverseScale;
+ if (scaleFactor < 0.5 || scaleFactor > 2.0) {
#ifdef QT_OPENGL_CACHE_AS_VBOS
- glDeleteBuffers(1, &cache->vbo);
- cache->vbo = 0;
- Q_ASSERT(cache->ibo == 0);
+ glDeleteBuffers(1, &cache->vbo);
+ cache->vbo = 0;
+ Q_ASSERT(cache->ibo == 0);
#else
- free(cache->vertices);
- Q_ASSERT(cache->indices == 0);
+ free(cache->vertices);
+ Q_ASSERT(cache->indices == nullptr);
#endif
- updateCache = true;
- }
+ updateCache = true;
}
} else {
- cache = new QGL2PEVectorPathCache;
+ cache = new QOpenGL2PEVectorPathCache;
data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath);
updateCache = true;
}
@@ -804,25 +902,26 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
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);
+ funcs.glGenBuffers(1, &cache->vbo);
+ funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ funcs.glBufferData(GL_ARRAY_BUFFER, floatSizeInBytes, vertexCoordinateArray.data(), GL_STATIC_DRAW);
cache->ibo = 0;
#else
cache->vertices = (float *) malloc(floatSizeInBytes);
memcpy(cache->vertices, vertexCoordinateArray.data(), floatSizeInBytes);
- cache->indices = 0;
+ cache->indices = nullptr;
#endif
}
prepareForDraw(currentBrush.isOpaque());
#ifdef QT_OPENGL_CACHE_AS_VBOS
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ uploadData(QT_VERTEX_COORD_ATTR, 0, cache->vertexCount);
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0);
#else
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, cache->vertices);
+ uploadData(QT_VERTEX_COORDS_ATTR, cache->vertices, cache->vertexCount * 2);
#endif
- glDrawArrays(cache->primitiveType, 0, cache->vertexCount);
+ funcs.glDrawArrays(cache->primitiveType, 0, cache->vertexCount);
} else {
// printf(" - Marking path as cachable...\n");
@@ -847,55 +946,53 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
if (useCache) {
QVectorPath::CacheEntry *data = path.lookupCacheData(q);
- QGL2PEVectorPathCache *cache;
+ QOpenGL2PEVectorPathCache *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) {
+ cache = (QOpenGL2PEVectorPathCache *) data->data;
+ // Check if scale factor is exceeded and regenerate if so...
+ qreal scaleFactor = cache->iscale / inverseScale;
+ if (scaleFactor < 0.5 || scaleFactor > 2.0) {
#ifdef QT_OPENGL_CACHE_AS_VBOS
- glDeleteBuffers(1, &cache->vbo);
- glDeleteBuffers(1, &cache->ibo);
+ glDeleteBuffers(1, &cache->vbo);
+ glDeleteBuffers(1, &cache->ibo);
#else
- free(cache->vertices);
- free(cache->indices);
+ free(cache->vertices);
+ free(cache->indices);
#endif
- updateCache = true;
- }
+ updateCache = true;
}
} else {
- cache = new QGL2PEVectorPathCache;
+ cache = new QOpenGL2PEVectorPathCache;
data = const_cast<QVectorPath &>(path).addCacheData(q, cache, cleanupVectorPath);
updateCache = true;
}
// Flatten the path at the current scale factor and fill it into the cache struct.
if (updateCache) {
- QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale));
+ QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale), 1, supportsElementIndexUint);
cache->vertexCount = polys.vertices.size() / 2;
cache->indexCount = polys.indices.size();
cache->primitiveType = GL_TRIANGLES;
cache->iscale = inverseScale;
cache->indexType = polys.indices.type();
#ifdef QT_OPENGL_CACHE_AS_VBOS
- glGenBuffers(1, &cache->vbo);
- glGenBuffers(1, &cache->ibo);
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
+ funcs.glGenBuffers(1, &cache->vbo);
+ funcs.glGenBuffers(1, &cache->ibo);
+ funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
if (polys.indices.type() == QVertexIndexVector::UnsignedInt)
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint32) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW);
+ funcs.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);
+ funcs.glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quint16) * polys.indices.size(), polys.indices.data(), GL_STATIC_DRAW);
QVarLengthArray<float> vertices(polys.vertices.size());
for (int i = 0; i < polys.vertices.size(); ++i)
vertices[i] = float(inverseScale * polys.vertices.at(i));
- glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
+ funcs.glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size(), vertices.data(), GL_STATIC_DRAW);
#else
cache->vertices = (float *) malloc(sizeof(float) * polys.vertices.size());
if (polys.indices.type() == QVertexIndexVector::UnsignedInt) {
@@ -912,21 +1009,21 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
prepareForDraw(currentBrush.isOpaque());
#ifdef QT_OPENGL_CACHE_AS_VBOS
- glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
+ funcs.glBindBuffer(GL_ARRAY_BUFFER, cache->vbo);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cache->ibo);
+ uploadData(QT_VERTEX_COORDS_ATTR, 0, cache->vertexCount);
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, 0);
if (cache->indexType == QVertexIndexVector::UnsignedInt)
- glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_INT, 0);
+ funcs.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);
+ funcs.glDrawElements(cache->primitiveType, cache->indexCount, GL_UNSIGNED_SHORT, 0);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ funcs.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);
+ uploadData(QT_VERTEX_COORDS_ATTR, cache->vertices, cache->vertexCount * 2);
+ const GLenum indexValueType = cache->indexType == QVertexIndexVector::UnsignedInt ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+ const bool useIndexVbo = uploadIndexData(cache->indices, indexValueType, cache->indexCount);
+ funcs.glDrawElements(cache->primitiveType, cache->indexCount, indexValueType, useIndexVbo ? nullptr : cache->indices);
#endif
} else {
@@ -934,7 +1031,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
// 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 (device->context()->format().stencilBufferSize() <= 0) {
// If there is no stencil buffer, triangulate the path instead.
QRectF bbox = path.controlPointRect();
@@ -944,18 +1041,17 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
&& (bbox.top() > -0x8000 * inverseScale)
&& (bbox.bottom() < 0x8000 * inverseScale);
if (withinLimits) {
- QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale));
+ QTriangleSet polys = qTriangulate(path, QTransform().scale(1 / inverseScale, 1 / inverseScale), 1, supportsElementIndexUint);
QVarLengthArray<float> vertices(polys.vertices.size());
for (int i = 0; i < polys.vertices.size(); ++i)
vertices[i] = float(inverseScale * polys.vertices.at(i));
prepareForDraw(currentBrush.isOpaque());
- 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());
+ uploadData(QT_VERTEX_COORDS_ATTR, vertices.constData(), vertices.size());
+ const GLenum indexValueType = funcs.hasOpenGLExtension(QOpenGLExtensions::ElementIndexUint) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+ const bool useIndexVbo = uploadIndexData(polys.indices.data(), indexValueType, polys.indices.size());
+ funcs.glDrawElements(GL_TRIANGLES, polys.indices.size(), indexValueType, useIndexVbo ? nullptr : polys.indices.data());
} else {
// We can't handle big, concave painter paths with OpenGL without stencil buffer.
qWarning("Painter path exceeds +/-32767 pixels.");
@@ -969,50 +1065,50 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
- glStencilMask(0xff);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ funcs.glStencilMask(0xff);
+ funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
if (q->state()->clipTestEnabled) {
// Pass when high bit is set, replace stencil value with current clip
- glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT);
+ funcs.glStencilFunc(GL_NOTEQUAL, q->state()->currentClip, GL_STENCIL_HIGH_BIT);
} else if (path.hasWindingFill()) {
// Pass when any bit is set, replace stencil value with 0
- glStencilFunc(GL_NOTEQUAL, 0, 0xff);
+ funcs.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);
+ funcs.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
}
prepareForDraw(currentBrush.isOpaque());
// Stencil the brush onto the dest buffer
composite(vertexCoordinateArray.boundingRect());
- glStencilMask(0);
+ funcs.glStencilMask(0);
updateClipScissorTest();
}
}
}
-void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
+void QOpenGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
int count,
int *stops,
int stopCount,
- const QGLRect &bounds,
+ const QOpenGLRect &bounds,
StencilFillMode mode)
{
Q_ASSERT(count || stops);
-// qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
- glStencilMask(0xff); // Enable stencil writes
+// qDebug("QOpenGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
+ funcs.glStencilMask(0xff); // Enable stencil writes
if (dirtyStencilRegion.intersects(currentScissorBounds)) {
const QRegion clearRegion = dirtyStencilRegion.intersected(currentScissorBounds);
- glClearStencil(0); // Clear to zero
+ funcs.glClearStencil(0); // Clear to zero
for (const QRect &rect : clearRegion) {
#ifndef QT_GL_NO_SCISSOR_TEST
setScissor(rect);
#endif
- glClear(GL_STENCIL_BUFFER_BIT);
+ funcs.glClear(GL_STENCIL_BUFFER_BIT);
}
dirtyStencilRegion -= currentScissorBounds;
@@ -1022,68 +1118,69 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
#endif
}
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
+ funcs.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
+ funcs.glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d
if (mode == WindingFillMode) {
Q_ASSERT(stops && !count);
if (q->state()->clipTestEnabled) {
// Flatten clip values higher than current clip, and set high bit to match current clip
- glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ funcs.glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
composite(bounds);
- glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT);
+ funcs.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);
+ funcs.glStencilFunc(GL_ALWAYS, 0, 0xff);
+ funcs.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);
+ funcs.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);
+ funcs.glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP);
+ funcs.glStencilMask(~GL_STENCIL_HIGH_BIT);
drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
if (q->state()->clipTestEnabled) {
// Clear high bit of stencil outside of path
- glStencilFunc(GL_EQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glStencilMask(GL_STENCIL_HIGH_BIT);
+ funcs.glStencilFunc(GL_EQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ funcs.glStencilMask(GL_STENCIL_HIGH_BIT);
composite(bounds);
}
} else if (mode == OddEvenFillMode) {
- glStencilMask(GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
+ funcs.glStencilMask(GL_STENCIL_HIGH_BIT);
+ funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
drawVertexArrays(data, stops, stopCount, GL_TRIANGLE_FAN);
} else { // TriStripStrokeFillMode
Q_ASSERT(count && !stops); // tristrips generated directly, so no vertexArray or stops
- glStencilMask(GL_STENCIL_HIGH_BIT);
+ funcs.glStencilMask(GL_STENCIL_HIGH_BIT);
#if 0
- glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
+ funcs.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
+ funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
#else
- glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+ funcs.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);
+ funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip | GL_STENCIL_HIGH_BIT,
+ ~GL_STENCIL_HIGH_BIT);
} else {
- glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
+ funcs.glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
}
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
+
+ uploadData(QT_VERTEX_COORDS_ATTR, data, count * 2);
+ funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, count);
#endif
}
// Enable color writes & disable stencil writes
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ funcs.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
/*
@@ -1091,30 +1188,30 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(const float *data,
restore the stencil buffer to a pristine state. The current clip region
is set to 1, and the rest to 0.
*/
-void QGL2PaintEngineExPrivate::resetClipIfNeeded()
+void QOpenGL2PaintEngineExPrivate::resetClipIfNeeded()
{
if (maxClip != (GL_STENCIL_HIGH_BIT - 1))
return;
- Q_Q(QGL2PaintEngineEx);
+ Q_Q(QOpenGL2PaintEngineEx);
useSimpleShader();
- glEnable(GL_STENCIL_TEST);
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+ funcs.glEnable(GL_STENCIL_TEST);
+ funcs.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
QRectF bounds = q->state()->matrix.inverted().mapRect(QRectF(0, 0, width, height));
- QGLRect rect(bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
+ QOpenGLRect 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);
+ funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, 0xff);
+ funcs.glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
+ funcs.glStencilMask(GL_STENCIL_HIGH_BIT);
composite(rect);
// Reset clipping to 1 and everything else to zero
- glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
- glStencilMask(0xff);
+ funcs.glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT);
+ funcs.glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE);
+ funcs.glStencilMask(0xff);
composite(rect);
q->state()->currentClip = 1;
@@ -1122,13 +1219,13 @@ void QGL2PaintEngineExPrivate::resetClipIfNeeded()
maxClip = 1;
- glStencilMask(0x0);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ funcs.glStencilMask(0x0);
+ funcs.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
}
-bool QGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache)
+bool QOpenGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphCache &cache)
{
- Q_Q(QGL2PaintEngineEx);
+ Q_Q(QOpenGL2PaintEngineEx);
Q_ASSERT(cache.transform().type() <= QTransform::TxScale);
@@ -1140,9 +1237,9 @@ bool QGL2PaintEngineExPrivate::prepareForCachedGlyphDraw(const QFontEngineGlyphC
return ret;
}
-bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
+bool QOpenGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
- if (brushTextureDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
+ if (brushTextureDirty && (mode == TextDrawingMode || mode == BrushDrawingMode))
updateBrushTexture();
if (compositionModeDirty)
@@ -1156,24 +1253,24 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
|| (q->state()->composition_mode == QPainter::CompositionMode_SourceOver
&& srcPixelsAreOpaque && !stateHasOpacity))
{
- glDisable(GL_BLEND);
+ funcs.glDisable(GL_BLEND);
} else {
- glEnable(GL_BLEND);
+ funcs.glEnable(GL_BLEND);
}
- QGLEngineShaderManager::OpacityMode opacityMode;
- if (mode == ImageArrayDrawingMode) {
- opacityMode = QGLEngineShaderManager::AttributeOpacity;
+ QOpenGLEngineShaderManager::OpacityMode opacityMode;
+ if (mode == ImageOpacityArrayDrawingMode) {
+ opacityMode = QOpenGLEngineShaderManager::AttributeOpacity;
} else {
- opacityMode = stateHasOpacity ? QGLEngineShaderManager::UniformOpacity
- : QGLEngineShaderManager::NoOpacity;
- if (stateHasOpacity && (mode != ImageDrawingMode)) {
+ opacityMode = stateHasOpacity ? QOpenGLEngineShaderManager::UniformOpacity
+ : QOpenGLEngineShaderManager::NoOpacity;
+ if (stateHasOpacity && (mode != ImageDrawingMode && mode != ImageArrayDrawingMode)) {
// Using a brush
bool brushIsPattern = (currentBrush.style() >= Qt::Dense1Pattern) &&
(currentBrush.style() <= Qt::DiagCrossPattern);
if ((currentBrush.style() == Qt::SolidPattern) || brushIsPattern)
- opacityMode = QGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader
+ opacityMode = QOpenGLEngineShaderManager::NoOpacity; // Global opacity handled by srcPixel shader
}
}
shaderManager->setOpacityMode(opacityMode);
@@ -1185,73 +1282,64 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
brushUniformsDirty = true;
opacityUniformDirty = true;
matrixUniformDirty = true;
- translateZUniformDirty = true;
}
- if (brushUniformsDirty && mode != ImageDrawingMode && mode != ImageArrayDrawingMode)
+ if (brushUniformsDirty && (mode == TextDrawingMode || mode == BrushDrawingMode))
updateBrushUniforms();
- if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
+ if (opacityMode == QOpenGLEngineShaderManager::UniformOpacity && opacityUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity);
opacityUniformDirty = false;
}
if (matrixUniformDirty && shaderManager->hasComplexGeometry()) {
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Matrix),
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::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)
+void QOpenGL2PaintEngineExPrivate::composite(const QOpenGLRect& boundingRect)
{
setCoords(staticVertexCoordinateArray, boundingRect);
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray);
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ uploadData(QT_VERTEX_COORDS_ATTR, staticVertexCoordinateArray, 8);
+ funcs.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
// Draws the vertex array as a set of <vertexArrayStops.size()> triangle fans.
-void QGL2PaintEngineExPrivate::drawVertexArrays(const float *data, int *stops, int stopCount,
+void QOpenGL2PaintEngineExPrivate::drawVertexArrays(const float *data, int *stops, int stopCount,
GLenum primitive)
{
// Now setup the pointer to the vertex array:
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, data);
+ uploadData(QT_VERTEX_COORDS_ATTR, data, stops[stopCount-1] * 2);
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);
+
+ funcs.glDrawArrays(primitive, previousStop, stop - previousStop);
previousStop = stop;
}
}
/////////////////////////////////// Public Methods //////////////////////////////////////////
-QGL2PaintEngineEx::QGL2PaintEngineEx()
- : QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
+QOpenGL2PaintEngineEx::QOpenGL2PaintEngineEx()
+ : QPaintEngineEx(*(new QOpenGL2PaintEngineExPrivate(this)))
{
+ gccaps &= ~QPaintEngine::RasterOpModes;
}
-QGL2PaintEngineEx::~QGL2PaintEngineEx()
+QOpenGL2PaintEngineEx::~QOpenGL2PaintEngineEx()
{
}
-void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
+void QOpenGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
if (qbrush_style(brush) == Qt::NoBrush)
return;
@@ -1260,19 +1348,19 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
d->fill(path);
}
-Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
+Q_GUI_EXPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp
-void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
+void QOpenGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
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)) {
+ QOpenGL2PaintEngineState *s = state();
+ if (qt_pen_is_cosmetic(pen, state()->renderHints) && !qt_scaleForTransform(s->transform(), nullptr)) {
// QTriangulatingStroker class is not meant to support cosmetically sheared strokes.
QPaintEngineEx::stroke(path, pen);
return;
@@ -1283,9 +1371,9 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
d->stroke(path, pen);
}
-void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
+void QOpenGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
{
- const QGL2PaintEngineState *s = q->state();
+ const QOpenGL2PaintEngineState *s = q->state();
if (snapToPixelGrid) {
snapToPixelGrid = false;
matrixDirty = true;
@@ -1323,14 +1411,9 @@ void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
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);
+ uploadData(QT_VERTEX_COORDS_ATTR, stroker.vertices(), stroker.vertexCount());
+ funcs.glDrawArrays(GL_TRIANGLE_STRIP, 0, stroker.vertexCount() / 2);
} else {
qreal width = qpen_widthf(pen) / 2;
if (width == 0)
@@ -1339,37 +1422,37 @@ void QGL2PaintEngineExPrivate::stroke(const QVectorPath &path, const QPen &pen)
? qMax(pen.miterLimit() * width, width)
: width;
- if (qt_pen_is_cosmetic(pen, s->renderHints))
+ if (qt_pen_is_cosmetic(pen, q->state()->renderHints))
extra = extra * inverseScale;
QRectF bounds = path.controlPointRect().adjusted(-extra, -extra, extra, extra);
fillStencilWithVertexArray(stroker.vertices(), stroker.vertexCount() / 2,
- 0, 0, bounds, QGL2PaintEngineExPrivate::TriStripStrokeFillMode);
+ nullptr, 0, bounds, QOpenGL2PaintEngineExPrivate::TriStripStrokeFillMode);
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ funcs.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);
+ funcs.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
prepareForDraw(false);
// Stencil the brush onto the dest buffer
composite(bounds);
- glStencilMask(0);
+ funcs.glStencilMask(0);
updateClipScissorTest();
}
}
-void QGL2PaintEngineEx::penChanged() { }
-void QGL2PaintEngineEx::brushChanged() { }
-void QGL2PaintEngineEx::brushOriginChanged() { }
+void QOpenGL2PaintEngineEx::penChanged() { }
+void QOpenGL2PaintEngineEx::brushChanged() { }
+void QOpenGL2PaintEngineEx::brushOriginChanged() { }
-void QGL2PaintEngineEx::opacityChanged()
+void QOpenGL2PaintEngineEx::opacityChanged()
{
-// qDebug("QGL2PaintEngineEx::opacityChanged()");
- Q_D(QGL2PaintEngineEx);
+// qDebug("QOpenGL2PaintEngineEx::opacityChanged()");
+ Q_D(QOpenGL2PaintEngineEx);
state()->opacityChanged = true;
Q_ASSERT(d->shaderManager);
@@ -1377,43 +1460,49 @@ void QGL2PaintEngineEx::opacityChanged()
d->opacityUniformDirty = true;
}
-void QGL2PaintEngineEx::compositionModeChanged()
+void QOpenGL2PaintEngineEx::compositionModeChanged()
{
-// qDebug("QGL2PaintEngineEx::compositionModeChanged()");
- Q_D(QGL2PaintEngineEx);
+// qDebug("QOpenGL2PaintEngineEx::compositionModeChanged()");
+ Q_D(QOpenGL2PaintEngineEx);
state()->compositionModeChanged = true;
d->compositionModeDirty = true;
}
-void QGL2PaintEngineEx::renderHintsChanged()
+void QOpenGL2PaintEngineEx::renderHintsChanged()
{
- Q_D(QGL2PaintEngineEx);
state()->renderHintsChanged = true;
-#if !defined(QT_OPENGL_ES_2)
+#ifndef QT_OPENGL_ES_2
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGL2PaintEngineEx);
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);
+ d->funcs.glEnable(GL_MULTISAMPLE);
else
- d->glDisable(GL_MULTISAMPLE);
- }
+ d->funcs.glDisable(GL_MULTISAMPLE);
QT_WARNING_POP
-#endif
+ }
+#endif // QT_OPENGL_ES_2
+
+ Q_D(QOpenGL2PaintEngineEx);
+ // This is a somewhat sneaky way of conceptually making the next call to
+ // updateTexture() use FoceUpdate for the TextureUpdateMode. We need this
+ // as new render hints may require updating the filter mode.
d->lastTextureUsed = GLuint(-1);
+
d->brushTextureDirty = true;
-// qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!");
+// qDebug("QOpenGL2PaintEngineEx::renderHintsChanged() not implemented!");
}
-void QGL2PaintEngineEx::transformChanged()
+void QOpenGL2PaintEngineEx::transformChanged()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
d->matrixDirty = true;
state()->matrixChanged = true;
}
@@ -1424,10 +1513,15 @@ 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)
+void QOpenGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
{
- Q_D(QGL2PaintEngineEx);
- QGLContext *ctx = d->ctx;
+ Q_D(QOpenGL2PaintEngineEx);
+ QOpenGLContext *ctx = d->ctx;
+
+ // Draw pixmaps that are really images as images since drawImage has
+ // better handling of non-default image formats.
+ if (pixmap.paintEngine()->type() == QPaintEngine::Raster && !pixmap.isQBitmap())
+ return drawImage(dest, pixmap.toImage(), src);
int max_texture_size = ctx->d_func()->maxTextureSize();
if (pixmap.width() > max_texture_size || pixmap.height() > max_texture_size) {
@@ -1443,38 +1537,23 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c
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);
+ GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
+ d->updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && !pixmap.hasAlpha();
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, texture->id);
- d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
+ d->shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc : QOpenGLEngineShaderManager::ImageSrc);
- 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);
- }
+ QOpenGLRect srcRect(src.left(), src.top(), src.right(), src.bottom());
+ d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap);
}
-void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
+void QOpenGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
Qt::ImageConversionFlags)
{
- Q_D(QGL2PaintEngineEx);
- QGLContext *ctx = d->ctx;
+ Q_D(QOpenGL2PaintEngineEx);
+ QOpenGLContext *ctx = d->ctx;
int max_texture_size = ctx->d_func()->maxTextureSize();
if (image.width() > max_texture_size || image.height() > max_texture_size) {
@@ -1490,45 +1569,56 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const
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
+ QOpenGLTextureUploader::BindOptions bindOption = QOpenGLTextureUploader::PremultipliedAlphaBindOption;
+ // Use specialized bind for formats we have specialized shaders for.
+ switch (image.format()) {
+ case QImage::Format_RGBA8888:
+ case QImage::Format_ARGB32:
+ case QImage::Format_RGBA64:
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::NonPremultipliedImageSrc);
+ bindOption = { };
+ break;
+ case QImage::Format_Alpha8:
+ if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::AlphaImageSrc);
+ bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption;
+ } else
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ break;
+ case QImage::Format_Grayscale8:
+ case QImage::Format_Grayscale16:
+ if (ctx->functions()->hasOpenGLFeature(QOpenGLFunctions::TextureRGFormats)) {
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::GrayscaleImageSrc);
+ bindOption = QOpenGLTextureUploader::UseRedForAlphaAndLuminanceBindOption;
+ } else
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ break;
+ default:
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ break;
+ }
- QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, bindOptions);
- GLuint id = texture->id;
+ ImageWithBindOptions imageWithOptions = { image, bindOption };
+ GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
+ d->updateTexture(QT_IMAGE_TEXTURE_UNIT, imageWithOptions, GL_CLAMP_TO_EDGE, filterMode);
- d->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)
+void QOpenGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
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
+ if (d->device->context()->format().alphaBufferSize() > 0 || s->matrix.type() > QTransform::TxTranslate
|| (s->composition_mode != QPainter::CompositionMode_Source
&& s->composition_mode != QPainter::CompositionMode_SourceOver))
{
@@ -1542,32 +1632,32 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem)
}
}
-bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
+bool QOpenGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
if (!d->shaderManager)
return false;
ensureActive();
d->transferMode(ImageDrawingMode);
- d->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
- d->glBindTexture(GL_TEXTURE_2D, textureId);
+ GLenum filterMode = state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
+ d->updateTexture(QT_IMAGE_TEXTURE_UNIT, textureId, GL_CLAMP_TO_EDGE, filterMode);
- QGLRect srcRect(src.left(), src.bottom(), src.right(), src.top());
+ d->shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
- d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE,
- state()->renderHints & QPainter::SmoothPixmapTransform, textureId);
+ QOpenGLRect srcRect(src.left(), src.bottom(), src.right(), src.top());
d->drawTexture(dest, srcRect, size, false);
+
return true;
}
-void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
+void QOpenGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
ensureActive();
- QGL2PaintEngineState *s = state();
+ QOpenGL2PaintEngineState *s = state();
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
@@ -1577,8 +1667,7 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
? ti.fontEngine->glyphFormat : d->glyphCacheFormat;
if (glyphFormat == QFontEngine::Format_A32) {
- if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()
- || d->device->alphaRequested() || txtype > QTransform::TxTranslate
+ if (d->device->context()->format().alphaBufferSize() > 0 || txtype > QTransform::TxTranslate
|| (state()->composition_mode != QPainter::CompositionMode_Source
&& state()->composition_mode != QPainter::CompositionMode_SourceOver))
{
@@ -1622,8 +1711,8 @@ namespace {
}
QSize cacheSize;
- QGL2PEXVertexArray vertexCoordinateArray;
- QGL2PEXVertexArray textureCoordinateArray;
+ QOpenGL2PEXVertexArray vertexCoordinateArray;
+ QOpenGL2PEXVertexArray textureCoordinateArray;
QFontEngine::GlyphFormat glyphFormat;
int cacheSerialNumber;
};
@@ -1633,14 +1722,40 @@ namespace {
// #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO
-void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat,
+bool QOpenGL2PaintEngineEx::shouldDrawCachedGlyphs(QFontEngine *fontEngine, const QTransform &t) const
+{
+ // The paint engine does not support projected cached glyph drawing
+ if (t.type() == QTransform::TxProject)
+ return false;
+
+ // The font engine might not support filling the glyph cache
+ // with the given transform applied, in which case we need to
+ // fall back to the QPainterPath code-path.
+ if (!fontEngine->supportsTransformation(t)) {
+ // Except that drawing paths is slow, so for scales between
+ // 0.5 and 2.0 we leave the glyph cache untransformed and deal
+ // with the transform ourselves when painting, resulting in
+ // drawing 1x cached glyphs with a smooth-scale.
+ float det = t.determinant();
+ if (det >= 0.25f && det <= 4.f) {
+ // Assuming the baseclass still agrees
+ return QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t);
+ }
+
+ return false; // Fall back to path-drawing
+ }
+
+ return QPaintEngineEx::shouldDrawCachedGlyphs(fontEngine, t);
+}
+
+void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat,
QStaticTextItem *staticTextItem)
{
- Q_Q(QGL2PaintEngineEx);
+ Q_Q(QOpenGL2PaintEngineEx);
- QGL2PaintEngineState *s = q->state();
+ QOpenGL2PaintEngineState *s = q->state();
- void *cacheKey = const_cast<QGLContext *>(QGLContextPrivate::contextGroup(ctx)->context());
+ void *cacheKey = ctx; // use context, not the shareGroup() -> the GL glyph cache uses FBOs which may not be shareable
bool recreateVertexArrays = false;
QTransform glyphCacheTransform;
@@ -1656,17 +1771,17 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
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);
+ QOpenGLTextureGlyphCache *cache =
+ (QOpenGLTextureGlyphCache *) fe->glyphCache(cacheKey, glyphFormat, glyphCacheTransform);
+ if (!cache || cache->glyphFormat() != glyphFormat || cache->contextGroup() == nullptr) {
+ cache = new QOpenGLTextureGlyphCache(glyphFormat, glyphCacheTransform);
fe->setGlyphCache(cacheKey, cache);
recreateVertexArrays = true;
}
if (staticTextItem->userDataNeedsUpdate) {
recreateVertexArrays = true;
- } else if (staticTextItem->userData() == 0) {
+ } else if (staticTextItem->userData() == nullptr) {
recreateVertexArrays = true;
} else if (staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) {
recreateVertexArrays = true;
@@ -1691,13 +1806,35 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
cache->populate(fe, staticTextItem->numGlyphs,
staticTextItem->glyphs, staticTextItem->glyphPositions);
}
- cache->fillInPendingGlyphs();
+
+ if (cache->hasPendingGlyphs()) {
+ // Filling in the glyphs binds and sets parameters, so we need to
+ // ensure that the glyph cache doesn't mess with whatever unit
+ // is currently active. Note that the glyph cache internally
+ // uses the image texture unit for blitting to the cache, while
+ // we switch between image and mask units when drawing.
+ static const GLenum glypchCacheTextureUnit = QT_IMAGE_TEXTURE_UNIT;
+ activateTextureUnit(glypchCacheTextureUnit);
+
+ cache->fillInPendingGlyphs();
+
+ // We assume the cache can be trusted on which texture was bound
+ lastTextureUsed = cache->texture();
+
+ // But since the brush and image texture units are possibly shared
+ // we may have to re-bind brush textures after filling in the cache.
+ brushTextureDirty = (QT_BRUSH_TEXTURE_UNIT == glypchCacheTextureUnit);
+ }
+ cache->setPaintEnginePrivate(nullptr);
}
if (cache->width() == 0 || cache->height() == 0)
return;
- transferMode(TextDrawingMode);
+ if (glyphFormat == QFontEngine::Format_ARGB)
+ transferMode(ImageArrayDrawingMode);
+ else
+ transferMode(TextDrawingMode);
int margin = fe->glyphMargin(glyphFormat);
@@ -1705,13 +1842,13 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
GLfloat dy = 1.0 / cache->height();
// Use global arrays by default
- QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray;
- QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray;
+ QOpenGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray;
+ QOpenGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray;
if (staticTextItem->useBackendOptimizations) {
- QOpenGLStaticTextUserData *userData = 0;
+ QOpenGLStaticTextUserData *userData = nullptr;
- if (staticTextItem->userData() == 0
+ if (staticTextItem->userData() == nullptr
|| staticTextItem->userData()->type != QStaticTextUserData::OpenGLUserData) {
userData = new QOpenGLStaticTextUserData();
@@ -1781,20 +1918,22 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
if (elementIndicesVBOId == 0)
- glGenBuffers(1, &elementIndicesVBOId);
+ funcs.glGenBuffers(1, &elementIndicesVBOId);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
- glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort),
- elementIndices.constData(), GL_STATIC_DRAW);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
+ funcs.glBufferData(GL_ELEMENT_ARRAY_BUFFER, elementIndices.size() * sizeof(GLushort),
+ elementIndices.constData(), GL_STATIC_DRAW);
#endif
} else {
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementIndicesVBOId);
#endif
}
- setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data());
- setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data());
+ if (glyphFormat != QFontEngine::Format_ARGB || recreateVertexArrays) {
+ uploadData(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinates->data(), vertexCoordinates->vertexCount() * 2);
+ uploadData(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinates->data(), textureCoordinates->vertexCount() * 2);
+ }
if (!snapToPixelGrid) {
snapToPixelGrid = true;
@@ -1812,7 +1951,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
Q_ASSERT(compMode == QPainter::CompositionMode_Source
|| compMode == QPainter::CompositionMode_SourceOver);
- shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass1);
+ shaderManager->setMaskType(QOpenGLEngineShaderManager::SubPixelMaskPass1);
if (pensBrush.style() == Qt::SolidPattern) {
// Solid patterns can get away with only one pass.
@@ -1833,9 +1972,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
opacityUniformDirty = true;
}
- glEnable(GL_BLEND);
- glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
- glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
+ funcs.glEnable(GL_BLEND);
+ funcs.glBlendFunc(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR);
+ funcs.glBlendColor(c.redF(), c.greenF(), c.blueF(), c.alphaF());
} else {
// Other brush styles need two passes.
@@ -1849,20 +1988,19 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
compositionModeDirty = false; // I can handle this myself, thank you very much
prepareForCachedGlyphDraw(*cache);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
+ funcs.glEnable(GL_BLEND);
+ funcs.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);
+ updateTexture(QT_MASK_TEXTURE_UNIT, cache->texture(), GL_REPEAT, GL_NEAREST, ForceUpdate);
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
+ funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
+ const bool useIndexVbo = uploadIndexData(elementIndices.data(), GL_UNSIGNED_SHORT, 6 * numGlyphs);
+ funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, useIndexVbo ? nullptr : elementIndices.data());
#endif
- shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMaskPass2);
+ shaderManager->setMaskType(QOpenGLEngineShaderManager::SubPixelMaskPass2);
if (compMode == QPainter::CompositionMode_Source) {
q->state()->opacity = oldOpacity;
@@ -1873,50 +2011,52 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat glyphFo
compositionModeDirty = false;
prepareForCachedGlyphDraw(*cache);
- glEnable(GL_BLEND);
- glBlendFunc(GL_ONE, GL_ONE);
+ funcs.glEnable(GL_BLEND);
+ funcs.glBlendFunc(GL_ONE, GL_ONE);
}
compositionModeDirty = true;
+ } else if (glyphFormat == QFontEngine::Format_ARGB) {
+ currentBrush = noBrush;
+ shaderManager->setSrcPixelType(QOpenGLEngineShaderManager::ImageSrc);
+ if (prepareForCachedGlyphDraw(*cache))
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
} else {
// Grayscale/mono glyphs
- shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
+ shaderManager->setMaskType(QOpenGLEngineShaderManager::PixelMask);
prepareForCachedGlyphDraw(*cache);
}
- QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest;
- if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) {
+ GLenum textureUnit = QT_MASK_TEXTURE_UNIT;
+ if (glyphFormat == QFontEngine::Format_ARGB)
+ textureUnit = QT_IMAGE_TEXTURE_UNIT;
- glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
- if (lastMaskTextureUsed != cache->texture()) {
- glBindTexture(GL_TEXTURE_2D, cache->texture());
- lastMaskTextureUsed = cache->texture();
- }
+ QOpenGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate) ?
+ QOpenGLTextureGlyphCache::Linear : QOpenGLTextureGlyphCache::Nearest;
- 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);
- }
+ GLenum glFilterMode = filterMode == QOpenGLTextureGlyphCache::Linear ? GL_LINEAR : GL_NEAREST;
+
+ TextureUpdateMode updateMode = UpdateIfNeeded;
+ if (cache->filterMode() != filterMode) {
+ updateMode = ForceUpdate;
+ cache->setFilterMode(filterMode);
}
+ updateTexture(textureUnit, cache->texture(), GL_REPEAT, glFilterMode, updateMode);
+
#if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO)
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+ funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, 0);
+ funcs.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else
- glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data());
+ const bool useIndexVbo = uploadIndexData(elementIndices.data(), GL_UNSIGNED_SHORT, 6 * numGlyphs);
+ funcs.glDrawElements(GL_TRIANGLE_STRIP, 6 * numGlyphs, GL_UNSIGNED_SHORT, useIndexVbo ? nullptr : elementIndices.data());
#endif
}
-void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
+void QOpenGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
// Use fallback for extended composition modes.
if (state()->composition_mode > QPainter::CompositionMode_Plus) {
QPaintEngineEx::drawPixmapFragments(fragments, fragmentCount, pixmap, hints);
@@ -1934,7 +2074,7 @@ void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *frag
}
-void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments,
+void QOpenGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragment *fragments,
int fragmentCount, const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints)
{
@@ -1962,8 +2102,8 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen
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);
+ QOpenGLPoint bottomRight(right * c - bottom * s, right * s + bottom * c);
+ QOpenGLPoint bottomLeft(-right * c - bottom * s, -right * s + bottom * c);
vertexCoordinateArray.addVertex(bottomRight.x + fragments[i].x, bottomRight.y + fragments[i].y);
vertexCoordinateArray.addVertex(-bottomLeft.x + fragments[i].x, -bottomLeft.y + fragments[i].y);
@@ -1972,7 +2112,7 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen
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,
+ QOpenGLRect src(fragments[i].sourceLeft * dx, fragments[i].sourceTop * dy,
(fragments[i].sourceLeft + fragments[i].width) * dx,
(fragments[i].sourceTop + fragments[i].height) * dy);
@@ -1988,58 +2128,100 @@ void QGL2PaintEngineExPrivate::drawPixmapFragments(const QPainter::PixmapFragmen
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(ImageOpacityArrayDrawingMode);
- transferMode(ImageArrayDrawingMode);
+ GLenum filterMode = q->state()->renderHints & QPainter::SmoothPixmapTransform ? GL_LINEAR : GL_NEAREST;
+ updateTexture(QT_IMAGE_TEXTURE_UNIT, pixmap, GL_CLAMP_TO_EDGE, filterMode);
bool isBitmap = pixmap.isQBitmap();
bool isOpaque = !isBitmap && (!pixmap.hasAlpha() || (hints & QPainter::OpaqueHint)) && allOpaque;
- 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);
+ shaderManager->setSrcPixelType(isBitmap ? QOpenGLEngineShaderManager::PatternSrc
+ : QOpenGLEngineShaderManager::ImageSrc);
if (prepareForDraw(isOpaque))
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::ImageTexture), QT_IMAGE_TEXTURE_UNIT);
if (isBitmap) {
QColor col = qt_premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
- shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::PatternColor), col);
+ shaderManager->currentProgram()->setUniformValue(location(QOpenGLEngineShaderManager::PatternColor), col);
}
- glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount);
+ funcs.glDrawArrays(GL_TRIANGLES, 0, 6 * fragmentCount);
}
-bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
+bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev)
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
-// qDebug("QGL2PaintEngineEx::begin()");
- if (pdev->devType() == QInternal::OpenGL)
- d->device = static_cast<QGLPaintDevice*>(pdev);
- else
- d->device = QGLPaintDevice::getDevice(pdev);
+ Q_ASSERT(pdev->devType() == QInternal::OpenGL);
+ d->device = static_cast<QOpenGLPaintDevice*>(pdev);
if (!d->device)
return false;
- d->ctx = d->device->context();
- d->ctx->d_ptr->active_engine = this;
+ d->device->ensureActiveTarget();
+
+ if (d->device->context() != QOpenGLContext::currentContext() || !d->device->context()) {
+ qWarning("QPainter::begin(): QOpenGLPaintDevice's context needs to be current");
+ return false;
+ }
+
+ if (d->ctx != QOpenGLContext::currentContext()
+ || (d->ctx && QOpenGLContext::currentContext() && d->ctx->format() != QOpenGLContext::currentContext()->format())) {
+ d->vertexBuffer.destroy();
+ d->texCoordBuffer.destroy();
+ d->opacityBuffer.destroy();
+ d->indexBuffer.destroy();
+ d->vao.destroy();
+ }
+
+ d->ctx = QOpenGLContext::currentContext();
+ d->ctx->d_func()->active_engine = this;
+
+ QOpenGLPaintDevicePrivate::get(d->device)->beginPaint();
+
+ d->funcs.initializeOpenGLFunctions();
+
+ // Generate a new Vertex Array Object if we don't have one already. We can
+ // only hit the VAO-based path when using a core profile context. This is
+ // because while non-core contexts can support VAOs via extensions, legacy
+ // components like the QtOpenGL module do not know about VAOs. There are
+ // still tests for QGL-QOpenGL paint engine interoperability, so keep the
+ // status quo for now, and avoid introducing a VAO in non-core contexts.
+ const bool needsVAO = d->ctx->format().profile() == QSurfaceFormat::CoreProfile
+ && d->ctx->format().version() >= qMakePair(3, 2);
+ if (needsVAO && !d->vao.isCreated()) {
+ bool created = d->vao.create();
+
+ // If we managed to create it then we have a profile that supports VAOs
+ if (created) {
+ d->vao.bind();
- d->resetOpenGLContextActiveEngine();
+ // Generate a new Vertex Buffer Object if we don't have one already
+ if (!d->vertexBuffer.isCreated()) {
+ d->vertexBuffer.create();
+ // Set its usage to StreamDraw, we will use this buffer only a few times before refilling it
+ d->vertexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
+ }
+ if (!d->texCoordBuffer.isCreated()) {
+ d->texCoordBuffer.create();
+ d->texCoordBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
+ }
+ if (!d->opacityBuffer.isCreated()) {
+ d->opacityBuffer.create();
+ d->opacityBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
+ }
+ if (!d->indexBuffer.isCreated()) {
+ d->indexBuffer.create();
+ d->indexBuffer.setUsagePattern(QOpenGLBuffer::StreamDraw);
+ }
+ }
+ }
+
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
+ d->vertexAttributeArraysEnabledState[i] = false;
const QSize sz = d->device->size();
d->width = sz.width();
@@ -2051,7 +2233,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->matrixDirty = true;
d->compositionModeDirty = true;
d->opacityUniformDirty = true;
- d->translateZUniformDirty = true;
d->needsSync = true;
d->useSystemClip = !systemClip().isEmpty();
d->currentBrush = QBrush();
@@ -2059,67 +2240,55 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
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->shaderManager = new QOpenGLEngineShaderManager(d->ctx);
- 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->funcs.glDisable(GL_STENCIL_TEST);
+ d->funcs.glDisable(GL_DEPTH_TEST);
+ d->funcs.glDisable(GL_SCISSOR_TEST);
d->glyphCacheFormat = QFontEngine::Format_A8;
-#if !defined(QT_OPENGL_ES_2)
- if (!d->ctx->contextHandle()->isOpenGLES()) {
+#ifndef QT_OPENGL_ES_2
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ d->funcs.glDisable(GL_MULTISAMPLE);
d->glyphCacheFormat = QFontEngine::Format_A32;
d->multisamplingAlwaysEnabled = false;
- } else {
- d->multisamplingAlwaysEnabled = d->device->format().sampleBuffers();
+ } else
+#endif // QT_OPENGL_ES_2
+ {
+ // OpenGL ES can't switch MSAA off, so if the gl paint device is
+ // multisampled, it's always multisampled.
+ d->multisamplingAlwaysEnabled = d->device->context()->format().samples() > 1;
}
-#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()
+bool QOpenGL2PaintEngineEx::end()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
+
+ QOpenGLPaintDevicePrivate::get(d->device)->endPaint();
- QGLContext *ctx = d->ctx;
- d->glUseProgram(0);
+ QOpenGLContext *ctx = d->ctx;
+ d->funcs.glUseProgram(0);
d->transferMode(BrushDrawingMode);
- d->device->endPaint();
- ctx->d_ptr->active_engine = 0;
- ctx->makeCurrent();
- d->resetOpenGLContextActiveEngine();
+ ctx->d_func()->active_engine = nullptr;
+
d->resetGLState();
delete d->shaderManager;
- d->shaderManager = 0;
+ d->shaderManager = nullptr;
d->currentBrush = QBrush();
#ifdef QT_OPENGL_CACHE_AS_VBOS
if (!d->unusedVBOSToClean.isEmpty()) {
- d->glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
+ glDeleteBuffers(d->unusedVBOSToClean.size(), d->unusedVBOSToClean.constData());
d->unusedVBOSToClean.clear();
}
if (!d->unusedIBOSToClean.isEmpty()) {
- d->glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
+ glDeleteBuffers(d->unusedIBOSToClean.size(), d->unusedIBOSToClean.constData());
d->unusedIBOSToClean.clear();
}
#endif
@@ -2127,40 +2296,42 @@ bool QGL2PaintEngineEx::end()
return false;
}
-void QGL2PaintEngineEx::ensureActive()
+void QOpenGL2PaintEngineEx::ensureActive()
{
- Q_D(QGL2PaintEngineEx);
- QGLContext *ctx = d->ctx;
+ Q_D(QOpenGL2PaintEngineEx);
+ QOpenGLContext *ctx = d->ctx;
+
+ if (d->vao.isCreated())
+ d->vao.bind();
- if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) {
- ctx->d_ptr->active_engine = this;
+ if (isActive() && ctx->d_func()->active_engine != this) {
+ ctx->d_func()->active_engine = this;
d->needsSync = true;
}
- d->device->ensureActiveTarget();
-
if (d->needsSync) {
+ d->device->ensureActiveTarget();
+
d->transferMode(BrushDrawingMode);
- d->glViewport(0, 0, d->width, d->height);
+ d->funcs.glViewport(0, 0, d->width, d->height);
d->needsSync = false;
- d->lastMaskTextureUsed = 0;
d->shaderManager->setDirty();
- d->ctx->d_func()->syncGlState();
+ d->syncGlState();
for (int i = 0; i < 3; ++i)
d->vertexAttribPointers[i] = (GLfloat*)-1; // Assume the pointers are clobbered
setState(state());
}
}
-void QGL2PaintEngineExPrivate::updateClipScissorTest()
+void QOpenGL2PaintEngineExPrivate::updateClipScissorTest()
{
- Q_Q(QGL2PaintEngineEx);
+ Q_Q(QOpenGL2PaintEngineEx);
if (q->state()->clipTestEnabled) {
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
+ funcs.glEnable(GL_STENCIL_TEST);
+ funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
} else {
- glDisable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0xff);
+ funcs.glDisable(GL_STENCIL_TEST);
+ funcs.glStencilFunc(GL_ALWAYS, 0, 0xff);
}
#ifdef QT_GL_NO_SCISSOR_TEST
@@ -2182,30 +2353,30 @@ void QGL2PaintEngineExPrivate::updateClipScissorTest()
currentScissorBounds = bounds;
if (bounds == QRect(0, 0, width, height)) {
- glDisable(GL_SCISSOR_TEST);
+ funcs.glDisable(GL_SCISSOR_TEST);
} else {
- glEnable(GL_SCISSOR_TEST);
+ funcs.glEnable(GL_SCISSOR_TEST);
setScissor(bounds);
}
#endif
}
-void QGL2PaintEngineExPrivate::setScissor(const QRect &rect)
+void QOpenGL2PaintEngineExPrivate::setScissor(const QRect &rect)
{
const int left = rect.left();
const int width = rect.width();
int bottom = height - (rect.top() + rect.height());
- if (device->isFlipped()) {
+ if (device->paintFlipped()) {
bottom = rect.top();
}
const int height = rect.height();
- glScissor(left, bottom, width, height);
+ funcs.glScissor(left, bottom, width, height);
}
-void QGL2PaintEngineEx::clipEnabledChanged()
+void QOpenGL2PaintEngineEx::clipEnabledChanged()
{
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
state()->clipChanged = true;
@@ -2215,19 +2386,19 @@ void QGL2PaintEngineEx::clipEnabledChanged()
d->systemStateChanged();
}
-void QGL2PaintEngineExPrivate::clearClip(uint value)
+void QOpenGL2PaintEngineExPrivate::clearClip(uint value)
{
dirtyStencilRegion -= currentScissorBounds;
- glStencilMask(0xff);
- glClearStencil(value);
- glClear(GL_STENCIL_BUFFER_BIT);
- glStencilMask(0x0);
+ funcs.glStencilMask(0xff);
+ funcs.glClearStencil(value);
+ funcs.glClear(GL_STENCIL_BUFFER_BIT);
+ funcs.glStencilMask(0x0);
q->state()->needsClipBufferClear = false;
}
-void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
+void QOpenGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
{
transferMode(BrushDrawingMode);
@@ -2250,15 +2421,15 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
clearClip(1);
if (path.isEmpty()) {
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
+ funcs.glEnable(GL_STENCIL_TEST);
+ funcs.glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
return;
}
if (q->state()->clipTestEnabled)
- glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT);
else
- glStencilFunc(GL_ALWAYS, 0, 0xff);
+ funcs.glStencilFunc(GL_ALWAYS, 0, 0xff);
vertexCoordinateArray.clear();
vertexCoordinateArray.addPath(path, inverseScale, false);
@@ -2266,45 +2437,45 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value)
if (!singlePass)
fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
- glColorMask(false, false, false, false);
- glEnable(GL_STENCIL_TEST);
+ funcs.glColorMask(false, false, false, false);
+ funcs.glEnable(GL_STENCIL_TEST);
useSimpleShader();
if (singlePass) {
// Under these conditions we can set the new stencil value in a single
// pass, by using the current value and the "new value" as the toggles
- glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT);
- glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
- glStencilMask(value ^ referenceClipValue);
+ funcs.glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT);
+ funcs.glStencilMask(value ^ referenceClipValue);
drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
} else {
- glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- glStencilMask(0xff);
+ funcs.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ funcs.glStencilMask(0xff);
if (!q->state()->clipTestEnabled && path.hasWindingFill()) {
// Pass when any clip bit is set, set high bit
- glStencilFunc(GL_NOTEQUAL, GL_STENCIL_HIGH_BIT, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilFunc(GL_NOTEQUAL, GL_STENCIL_HIGH_BIT, ~GL_STENCIL_HIGH_BIT);
composite(vertexCoordinateArray.boundingRect());
}
// Pass when high bit is set, replace stencil value with new clip value
- glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT);
+ funcs.glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT);
composite(vertexCoordinateArray.boundingRect());
}
- glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
- glStencilMask(0);
+ funcs.glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT);
+ funcs.glStencilMask(0);
- glColorMask(true, true, true, true);
+ funcs.glColorMask(true, true, true, true);
}
-void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
+void QOpenGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
{
-// qDebug("QGL2PaintEngineEx::clip()");
- Q_D(QGL2PaintEngineEx);
+// qDebug("QOpenGL2PaintEngineEx::clip()");
+ Q_D(QOpenGL2PaintEngineEx);
state()->clipChanged = true;
@@ -2363,15 +2534,15 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
}
}
-void QGL2PaintEngineExPrivate::regenerateClip()
+void QOpenGL2PaintEngineExPrivate::regenerateClip()
{
systemStateChanged();
replayClipOperations();
}
-void QGL2PaintEngineExPrivate::systemStateChanged()
+void QOpenGL2PaintEngineExPrivate::systemStateChanged()
{
- Q_Q(QGL2PaintEngineEx);
+ Q_Q(QOpenGL2PaintEngineEx);
q->state()->clipChanged = true;
@@ -2379,8 +2550,9 @@ void QGL2PaintEngineExPrivate::systemStateChanged()
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;
+ //QWidgetPrivate *widgetPrivate = qt_widget_private(static_cast<QWidget *>(currentClipDevice)->window());
+ //useSystemClip = widgetPrivate->extra && widgetPrivate->extra->inRenderWithPainter;
+ useSystemClip = true;
} else {
useSystemClip = true;
}
@@ -2417,23 +2589,14 @@ void QGL2PaintEngineExPrivate::systemStateChanged()
}
}
-void QGL2PaintEngineEx::setTranslateZ(GLfloat z)
+void QOpenGL2PaintEngineEx::setState(QPainterState *new_state)
{
- Q_D(QGL2PaintEngineEx);
- if (d->translateZ != z) {
- d->translateZ = z;
- d->translateZUniformDirty = true;
- }
-}
-
-void QGL2PaintEngineEx::setState(QPainterState *new_state)
-{
- // qDebug("QGL2PaintEngineEx::setState()");
+ // qDebug("QOpenGL2PaintEngineEx::setState()");
- Q_D(QGL2PaintEngineEx);
+ Q_D(QOpenGL2PaintEngineEx);
- QGL2PaintEngineState *s = static_cast<QGL2PaintEngineState *>(new_state);
- QGL2PaintEngineState *old_state = state();
+ QOpenGL2PaintEngineState *s = static_cast<QOpenGL2PaintEngineState *>(new_state);
+ QOpenGL2PaintEngineState *old_state = state();
QPaintEngineEx::setState(s);
@@ -2462,23 +2625,23 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state)
if (old_state == s || old_state->clipChanged) {
if (old_state && old_state != s && old_state->canRestoreClip) {
d->updateClipScissorTest();
- d->glDepthFunc(GL_LEQUAL);
+ d->funcs.glDepthFunc(GL_LEQUAL);
} else {
d->regenerateClip();
}
}
}
-QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
+QPainterState *QOpenGL2PaintEngineEx::createState(QPainterState *orig) const
{
if (orig)
- const_cast<QGL2PaintEngineEx *>(this)->ensureActive();
+ const_cast<QOpenGL2PaintEngineEx *>(this)->ensureActive();
- QGL2PaintEngineState *s;
+ QOpenGL2PaintEngineState *s;
if (!orig)
- s = new QGL2PaintEngineState();
+ s = new QOpenGL2PaintEngineState();
else
- s = new QGL2PaintEngineState(*static_cast<QGL2PaintEngineState *>(orig));
+ s = new QOpenGL2PaintEngineState(*static_cast<QOpenGL2PaintEngineState *>(orig));
s->matrixChanged = false;
s->compositionModeChanged = false;
@@ -2489,7 +2652,7 @@ QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
return s;
}
-QGL2PaintEngineState::QGL2PaintEngineState(QGL2PaintEngineState &other)
+QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other)
: QPainterState(other)
{
isNew = true;
@@ -2500,7 +2663,7 @@ QGL2PaintEngineState::QGL2PaintEngineState(QGL2PaintEngineState &other)
rectangleClip = other.rectangleClip;
}
-QGL2PaintEngineState::QGL2PaintEngineState()
+QOpenGL2PaintEngineState::QOpenGL2PaintEngineState()
{
isNew = true;
needsClipBufferClear = true;
@@ -2508,8 +2671,32 @@ QGL2PaintEngineState::QGL2PaintEngineState()
canRestoreClip = true;
}
-QGL2PaintEngineState::~QGL2PaintEngineState()
+QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState()
+{
+}
+
+void QOpenGL2PaintEngineExPrivate::setVertexAttribArrayEnabled(int arrayIndex, bool enabled)
+{
+ Q_ASSERT(arrayIndex < QT_GL_VERTEX_ARRAY_TRACKED_COUNT);
+
+ if (vertexAttributeArraysEnabledState[arrayIndex] && !enabled)
+ funcs.glDisableVertexAttribArray(arrayIndex);
+
+ if (!vertexAttributeArraysEnabledState[arrayIndex] && enabled)
+ funcs.glEnableVertexAttribArray(arrayIndex);
+
+ vertexAttributeArraysEnabledState[arrayIndex] = enabled;
+}
+
+void QOpenGL2PaintEngineExPrivate::syncGlState()
{
+ for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i) {
+ if (vertexAttributeArraysEnabledState[i])
+ funcs.glEnableVertexAttribArray(i);
+ else
+ funcs.glDisableVertexAttribArray(i);
+ }
}
+
QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/qopenglpaintengine_p.h
index 762aac2f65..9dc92e3810 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/qopenglpaintengine_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QPAINTENGINEEX_OPENGL2_P_H
-#define QPAINTENGINEEX_OPENGL2_P_H
+#ifndef QOPENGLPAINTENGINE_P_H
+#define QOPENGLPAINTENGINE_P_H
//
// W A R N I N G
@@ -53,39 +53,46 @@
#include <QDebug>
+#include <qopenglpaintdevice.h>
+
#include <private/qpaintengineex_p.h>
-#include <private/qglengineshadermanager_p.h>
-#include <private/qgl2pexvertexarray_p.h>
-#include <private/qglpaintdevice_p.h>
+#include <private/qopenglengineshadermanager_p.h>
+#include <private/qopengl2pexvertexarray_p.h>
#include <private/qfontengine_p.h>
#include <private/qdatabuffer_p.h>
#include <private/qtriangulatingstroker_p.h>
+
#include <private/qopenglextensions_p.h>
+#include <QOpenGLVertexArrayObject>
+#include <QOpenGLBuffer>
+
enum EngineMode {
ImageDrawingMode,
TextDrawingMode,
BrushDrawingMode,
- ImageArrayDrawingMode
+ ImageArrayDrawingMode,
+ ImageOpacityArrayDrawingMode
};
QT_BEGIN_NAMESPACE
#define GL_STENCIL_HIGH_BIT GLuint(0x80)
+#define QT_UNKNOWN_TEXTURE_UNIT GLuint(-1)
+#define QT_DEFAULT_TEXTURE_UNIT GLuint(0)
#define QT_BRUSH_TEXTURE_UNIT GLuint(0)
#define QT_IMAGE_TEXTURE_UNIT GLuint(0) //Can be the same as brush texture unit
#define QT_MASK_TEXTURE_UNIT GLuint(1)
#define QT_BACKGROUND_TEXTURE_UNIT GLuint(2)
-class QGL2PaintEngineExPrivate;
+class QOpenGL2PaintEngineExPrivate;
-
-class QGL2PaintEngineState : public QPainterState
+class QOpenGL2PaintEngineState : public QPainterState
{
public:
- QGL2PaintEngineState(QGL2PaintEngineState &other);
- QGL2PaintEngineState();
- ~QGL2PaintEngineState();
+ QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other);
+ QOpenGL2PaintEngineState();
+ ~QOpenGL2PaintEngineState();
uint isNew : 1;
uint needsClipBufferClear : 1;
@@ -101,12 +108,12 @@ public:
QRect rectangleClip;
};
-class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
+class Q_OPENGL_EXPORT QOpenGL2PaintEngineEx : public QPaintEngineEx
{
- Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
+ Q_DECLARE_PRIVATE(QOpenGL2PaintEngineEx)
public:
- QGL2PaintEngineEx();
- ~QGL2PaintEngineEx();
+ QOpenGL2PaintEngineEx();
+ ~QOpenGL2PaintEngineEx();
bool begin(QPaintDevice *device) override;
void ensureActive();
@@ -139,11 +146,11 @@ public:
virtual void setState(QPainterState *s) override;
virtual QPainterState *createState(QPainterState *orig) const override;
- inline QGL2PaintEngineState *state() {
- return static_cast<QGL2PaintEngineState *>(QPaintEngineEx::state());
+ inline QOpenGL2PaintEngineState *state() {
+ return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
- inline const QGL2PaintEngineState *state() const {
- return static_cast<const QGL2PaintEngineState *>(QPaintEngineEx::state());
+ inline const QOpenGL2PaintEngineState *state() const {
+ return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
void beginNativePainting() override;
@@ -157,15 +164,19 @@ public:
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)
+ Q_DISABLE_COPY_MOVE(QOpenGL2PaintEngineEx)
+
+ friend class QOpenGLEngineShaderManager;
};
-class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate, protected QOpenGLExtensions
+// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
+// all the GL2 engine uses:
+#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
+
+class QOpenGL2PaintEngineExPrivate : public QPaintEngineExPrivate
{
- Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
+ Q_DECLARE_PUBLIC(QOpenGL2PaintEngineEx)
public:
enum StencilFillMode {
OddEvenFillMode,
@@ -173,7 +184,7 @@ public:
TriStripStrokeFillMode
};
- QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
+ QOpenGL2PaintEngineExPrivate(QOpenGL2PaintEngineEx *q_ptr) :
q(q_ptr),
shaderManager(nullptr),
width(0), height(0),
@@ -184,45 +195,54 @@ public:
snapToPixelGrid(false),
nativePaintingActive(false),
inverseScale(1),
- lastMaskTextureUsed(0),
- translateZ(0)
+ lastTextureUnitUsed(QT_UNKNOWN_TEXTURE_UNIT),
+ vertexBuffer(QOpenGLBuffer::VertexBuffer),
+ texCoordBuffer(QOpenGLBuffer::VertexBuffer),
+ opacityBuffer(QOpenGLBuffer::VertexBuffer),
+ indexBuffer(QOpenGLBuffer::IndexBuffer)
{ }
- ~QGL2PaintEngineExPrivate();
+ ~QOpenGL2PaintEngineExPrivate();
void updateBrushTexture();
void updateBrushUniforms();
void updateMatrix();
void updateCompositionMode();
- void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
+
+ enum TextureUpdateMode { UpdateIfNeeded, ForceUpdate };
+ template<typename T>
+ void updateTexture(GLenum textureUnit, const T &texture, GLenum wrapMode, GLenum filterMode, TextureUpdateMode updateMode = UpdateIfNeeded);
+ template<typename T>
+ GLuint bindTexture(const T &texture);
+ void activateTextureUnit(GLenum textureUnit);
void resetGLState();
- 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 drawTexture(const QOpenGLRect& dest, const QOpenGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints);
void drawCachedGlyphs(QFontEngine::GlyphFormat glyphFormat, QStaticTextItem *staticTextItem);
// Calls glVertexAttributePointer if the pointer has changed
- inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
+ inline void uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count);
+ inline bool uploadIndexData(const void *data, GLenum indexValueType, GLuint count);
// draws whatever is in the vertex array:
void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
- void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
+ void drawVertexArrays(QOpenGL2PEXVertexArray &vertexArray, GLenum primitive) {
drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
}
// Composites the bounding rect onto dest buffer:
- void composite(const QGLRect& boundingRect);
+ void composite(const QOpenGLRect& 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) {
+ void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QOpenGLRect &bounds, StencilFillMode mode);
+ void fillStencilWithVertexArray(QOpenGL2PEXVertexArray& vertexArray, bool useWindingFill) {
fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
vertexArray.boundingRect(),
useWindingFill ? WindingFillMode : OddEvenFillMode);
@@ -233,7 +253,7 @@ public:
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) {
+ inline GLuint location(const QOpenGLEngineShaderManager::Uniform uniform) {
return shaderManager->getUniformLocation(uniform);
}
@@ -246,20 +266,25 @@ public:
void regenerateClip();
void systemStateChanged() override;
+ void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
+ void syncGlState();
- static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
- static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
+ static QOpenGLEngineShaderManager* shaderManagerForEngine(QOpenGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
+ static QOpenGL2PaintEngineExPrivate *getData(QOpenGL2PaintEngineEx *engine) { return engine->d_func(); }
static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
+ QOpenGLExtensions funcs;
- QGL2PaintEngineEx* q;
- QGLEngineShaderManager* shaderManager;
- QGLPaintDevice* device;
+ QOpenGL2PaintEngineEx* q;
+ QOpenGLEngineShaderManager* shaderManager;
+ QOpenGLPaintDevice* device;
int width, height;
- QGLContext *ctx;
+ QOpenGLContext *ctx;
EngineMode mode;
QFontEngine::GlyphFormat glyphCacheFormat;
+ bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
+
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
bool compositionModeDirty;
@@ -267,7 +292,6 @@ public:
bool brushUniformsDirty;
bool opacityUniformDirty;
bool matrixUniformDirty;
- bool translateZUniformDirty;
bool stencilClean; // Has the stencil not been used for clipping so far?
bool useSystemClip;
@@ -278,10 +302,10 @@ public:
QBrush currentBrush; // May not be the state's brush!
const QBrush noBrush;
- QPixmap currentBrushPixmap;
+ QImage currentBrushImage;
- QGL2PEXVertexArray vertexCoordinateArray;
- QGL2PEXVertexArray textureCoordinateArray;
+ QOpenGL2PEXVertexArray vertexCoordinateArray;
+ QOpenGL2PEXVertexArray textureCoordinateArray;
QVector<GLushort> elementIndices;
GLuint elementIndicesVBOId;
QDataBuffer<GLfloat> opacityArray;
@@ -293,42 +317,79 @@ public:
GLfloat pmvMatrix[3][3];
GLfloat inverseScale;
+ GLenum lastTextureUnitUsed;
GLuint lastTextureUsed;
- GLuint lastMaskTextureUsed;
+
+ QOpenGLVertexArrayObject vao;
+ QOpenGLBuffer vertexBuffer;
+ QOpenGLBuffer texCoordBuffer;
+ QOpenGLBuffer opacityBuffer;
+ QOpenGLBuffer indexBuffer;
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)
+void QOpenGL2PaintEngineExPrivate::uploadData(unsigned int arrayIndex, const GLfloat *data, GLuint count)
{
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);
+
+ // If a vertex array object is created we have a profile that supports them
+ // and we will upload the data via a QOpenGLBuffer. Otherwise we will use
+ // the legacy way of uploading the data via glVertexAttribPointer.
+ if (vao.isCreated()) {
+ if (arrayIndex == QT_VERTEX_COORDS_ATTR) {
+ vertexBuffer.bind();
+ vertexBuffer.allocate(data, count * sizeof(float));
+ }
+ if (arrayIndex == QT_TEXTURE_COORDS_ATTR) {
+ texCoordBuffer.bind();
+ texCoordBuffer.allocate(data, count * sizeof(float));
+ }
+ if (arrayIndex == QT_OPACITY_ATTR) {
+ opacityBuffer.bind();
+ opacityBuffer.allocate(data, count * sizeof(float));
+ }
+ if (arrayIndex == QT_OPACITY_ATTR)
+ funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, nullptr);
+ else
+ funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
+ } else {
+ // If we already uploaded the data we don't have to do it again
+ if (data == vertexAttribPointers[arrayIndex])
+ return;
+
+ // Store the data in cache and upload it to the graphics card.
+ vertexAttribPointers[arrayIndex] = data;
+ if (arrayIndex == QT_OPACITY_ATTR)
+ funcs.glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, data);
+ else
+ funcs.glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, data);
+ }
+}
+
+bool QOpenGL2PaintEngineExPrivate::uploadIndexData(const void *data, GLenum indexValueType, GLuint count)
+{
+ // Follow the uploadData() logic: VBOs are used only when VAO support is available.
+ // Otherwise the legacy client-side pointer path is used.
+ if (vao.isCreated()) {
+ Q_ASSERT(indexValueType == GL_UNSIGNED_SHORT || indexValueType == GL_UNSIGNED_INT);
+ indexBuffer.bind();
+ indexBuffer.allocate(data, count * (indexValueType == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32)));
+ return true;
+ }
+ return false;
}
QT_END_NAMESPACE
-#endif // QPAINTENGINEEX_OPENGL2_P_H
+#endif
diff --git a/src/opengl/qopenglpixeltransferoptions.cpp b/src/opengl/qopenglpixeltransferoptions.cpp
new file mode 100644
index 0000000000..aa1af3b092
--- /dev/null
+++ b/src/opengl/qopenglpixeltransferoptions.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qopenglpixeltransferoptions.h"
+#include <QSharedData>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ * \class QOpenGLPixelTransferOptions
+ *
+ * \brief The QOpenGLPixelTransferOptions class describes the pixel storage
+ * modes that affect the unpacking of pixels during texture upload.
+ */
+
+/*!
+ * \fn QOpenGLPixelTransferOptions & QOpenGLPixelTransferOptions::operator=(QOpenGLPixelTransferOptions &&other)
+ * \internal
+ */
+
+/*!
+ * \fn void QOpenGLPixelTransferOptions::swap(QOpenGLPixelTransferOptions &other)
+ * \internal
+ */
+
+class QOpenGLPixelTransferOptionsData : public QSharedData
+{
+public:
+ QOpenGLPixelTransferOptionsData()
+ : alignment(4)
+ , skipImages(0)
+ , skipRows(0)
+ , skipPixels(0)
+ , imageHeight(0)
+ , rowLength(0)
+ , lsbFirst(false)
+ , swapBytes(false)
+ {}
+
+ int alignment;
+ int skipImages;
+ int skipRows;
+ int skipPixels;
+ int imageHeight;
+ int rowLength;
+ bool lsbFirst;
+ bool swapBytes;
+};
+
+/*!
+ * Constructs a new QOpenGLPixelTransferOptions instance with the default settings.
+ */
+QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions()
+ : data(new QOpenGLPixelTransferOptionsData)
+{
+}
+
+/*!
+ * \internal
+ */
+QOpenGLPixelTransferOptions::QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &rhs)
+ : data(rhs.data)
+{
+}
+
+/*!
+ * \internal
+ */
+QOpenGLPixelTransferOptions &QOpenGLPixelTransferOptions::operator=(const QOpenGLPixelTransferOptions &rhs)
+{
+ if (this != &rhs)
+ data.operator=(rhs.data);
+ return *this;
+}
+
+/*!
+ * Destructor.
+ */
+QOpenGLPixelTransferOptions::~QOpenGLPixelTransferOptions()
+{
+}
+
+/*!
+ * Sets the \a alignment requirements for each pixel row. Corresponds to \c GL_UNPACK_ALIGNMENT.
+ * The default value is 4, as specified by OpenGL.
+ */
+void QOpenGLPixelTransferOptions::setAlignment(int alignment)
+{
+ data->alignment = alignment;
+}
+
+/*!
+ * \return the current alignment requirement for each pixel row.
+ */
+int QOpenGLPixelTransferOptions::alignment() const
+{
+ return data->alignment;
+}
+
+/*!
+ * Sets the number of images that are skipped to \a skipImages.
+ * Corresponds to \c GL_UNPACK_SKIP_IMAGES. Equivalent to incrementing the pointer
+ * passed to QOpenGLTexture::setData(). The default value is 0.
+ */
+void QOpenGLPixelTransferOptions::setSkipImages(int skipImages)
+{
+ data->skipImages = skipImages;
+}
+
+/*!
+ * \return the number of images that are skipped.
+ */
+int QOpenGLPixelTransferOptions::skipImages() const
+{
+ return data->skipImages;
+}
+
+/*!
+ * Sets the number of rows that are skipped to \a skipRows.
+ * Corresponds to \c GL_UNPACK_SKIP_ROWS. Equivalent to incrementing the pointer
+ * passed to QOpenGLTexture::setData(). The default value is 0.
+ */
+void QOpenGLPixelTransferOptions::setSkipRows(int skipRows)
+{
+ data->skipRows = skipRows;
+}
+
+/*!
+ * \return the number of rows that are skipped.
+ */
+int QOpenGLPixelTransferOptions::skipRows() const
+{
+ return data->skipRows;
+}
+
+/*!
+ * Sets the number of pixels that are skipped to \a skipPixels.
+ * Corresponds to \c GL_UNPACK_SKIP_PIXELS. Equivalent to incrementing the pointer
+ * passed to QOpenGLTexture::setData(). The default value is 0.
+ */
+void QOpenGLPixelTransferOptions::setSkipPixels(int skipPixels)
+{
+ data->skipPixels = skipPixels;
+}
+
+/*!
+ * \return the number of pixels that are skipped.
+ */
+int QOpenGLPixelTransferOptions::skipPixels() const
+{
+ return data->skipPixels;
+}
+
+/*!
+ * Sets the image height for 3D textures to \a imageHeight.
+ * Corresponds to \c GL_UNPACK_IMAGE_HEIGHT.
+ * The default value is 0.
+ */
+void QOpenGLPixelTransferOptions::setImageHeight(int imageHeight)
+{
+ data->imageHeight = imageHeight;
+}
+
+/*!
+ * \return the currently set image height.
+ */
+int QOpenGLPixelTransferOptions::imageHeight() const
+{
+ return data->imageHeight;
+}
+
+/*!
+ * Sets the number of pixels in a row to \a rowLength.
+ * Corresponds to \c GL_UNPACK_ROW_LENGTH.
+ * The default value is 0.
+ */
+void QOpenGLPixelTransferOptions::setRowLength(int rowLength)
+{
+ data->rowLength = rowLength;
+}
+
+/*!
+ * \return the currently set row length.
+ */
+int QOpenGLPixelTransferOptions::rowLength() const
+{
+ return data->rowLength;
+}
+
+/*!
+ * \a lsbFirst specifies if bits within a byte are ordered from least to most significat.
+ * The default value is \c false, meaning that the first bit in each byte is the
+ * most significant one. This is significant for bitmap data only.
+ * Corresponds to \c GL_UNPACK_LSB_FIRST.
+ */
+void QOpenGLPixelTransferOptions::setLeastSignificantByteFirst(bool lsbFirst)
+{
+ data->lsbFirst = lsbFirst;
+}
+
+/*!
+ * \return \c true if bits within a byte are ordered from least to most significant.
+ */
+bool QOpenGLPixelTransferOptions::isLeastSignificantBitFirst() const
+{
+ return data->lsbFirst;
+}
+
+/*!
+ * \a swapBytes specifies if the byte ordering for multibyte components is reversed.
+ * The default value is \c false.
+ * Corresponds to \c GL_UNPACK_SWAP_BYTES.
+ */
+void QOpenGLPixelTransferOptions::setSwapBytesEnabled(bool swapBytes)
+{
+ data->swapBytes = swapBytes;
+}
+
+/*!
+ * \return \c true if the byte ordering for multibyte components is reversed.
+ */
+bool QOpenGLPixelTransferOptions::isSwapBytesEnabled() const
+{
+ return data->swapBytes;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopenglpixeltransferoptions.h b/src/opengl/qopenglpixeltransferoptions.h
new file mode 100644
index 0000000000..252c2a2f1e
--- /dev/null
+++ b/src/opengl/qopenglpixeltransferoptions.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QOPENGLPIXELUPLOADOPTIONS_H
+#define QOPENGLPIXELUPLOADOPTIONS_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#if !defined(QT_NO_OPENGL)
+
+#include <QtCore/QSharedDataPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLPixelTransferOptionsData;
+
+class Q_OPENGL_EXPORT QOpenGLPixelTransferOptions
+{
+public:
+ QOpenGLPixelTransferOptions();
+ QOpenGLPixelTransferOptions(const QOpenGLPixelTransferOptions &);
+ QOpenGLPixelTransferOptions &operator=(QOpenGLPixelTransferOptions &&other) noexcept
+ { swap(other); return *this; }
+ QOpenGLPixelTransferOptions &operator=(const QOpenGLPixelTransferOptions &);
+ ~QOpenGLPixelTransferOptions();
+
+ void swap(QOpenGLPixelTransferOptions &other) noexcept
+ { data.swap(other.data); }
+
+ void setAlignment(int alignment);
+ int alignment() const;
+
+ void setSkipImages(int skipImages);
+ int skipImages() const;
+
+ void setSkipRows(int skipRows);
+ int skipRows() const;
+
+ void setSkipPixels(int skipPixels);
+ int skipPixels() const;
+
+ void setImageHeight(int imageHeight);
+ int imageHeight() const;
+
+ void setRowLength(int rowLength);
+ int rowLength() const;
+
+ void setLeastSignificantByteFirst(bool lsbFirst);
+ bool isLeastSignificantBitFirst() const;
+
+ void setSwapBytesEnabled(bool swapBytes);
+ bool isSwapBytesEnabled() const;
+
+private:
+ QSharedDataPointer<QOpenGLPixelTransferOptionsData> data;
+};
+
+Q_DECLARE_SHARED(QOpenGLPixelTransferOptions)
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLPIXELUPLOADOPTIONS_H
diff --git a/src/opengl/qopenglqueryhelper_p.h b/src/opengl/qopenglqueryhelper_p.h
new file mode 100644
index 0000000000..f3ed997f98
--- /dev/null
+++ b/src/opengl/qopenglqueryhelper_p.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QOPENGLQUERYHELPER_P_H
+#define QOPENGLQUERYHELPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#if !defined(QT_OPENGL_ES_2)
+
+#include <QtGui/QOpenGLContext>
+
+QT_BEGIN_NAMESPACE
+
+// Helper class used by QOpenGLTimerQuery and later will be used by
+// QOpenGLOcclusionQuery
+class QOpenGLQueryHelper
+{
+public:
+ QOpenGLQueryHelper(QOpenGLContext *context)
+ : GetQueryObjectuiv(nullptr),
+ GetQueryObjectiv(nullptr),
+ GetQueryiv(nullptr),
+ EndQuery(nullptr),
+ BeginQuery(nullptr),
+ IsQuery(nullptr),
+ DeleteQueries(nullptr),
+ GenQueries(nullptr),
+ GetInteger64v(nullptr),
+ GetQueryObjectui64v(nullptr),
+ GetQueryObjecti64v(nullptr),
+ QueryCounter(nullptr)
+ {
+ Q_ASSERT(context);
+
+ // Core in OpenGL >=1.5
+ GetQueryObjectuiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint *)>(context->getProcAddress("glGetQueryObjectuiv"));
+ GetQueryObjectiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint *)>(context->getProcAddress("glGetQueryObjectiv"));
+ GetQueryiv = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLenum , GLint *)>(context->getProcAddress("glGetQueryiv"));
+ EndQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glEndQuery"));
+ BeginQuery = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLuint )>(context->getProcAddress("glBeginQuery"));
+ IsQuery = reinterpret_cast<GLboolean (QOPENGLF_APIENTRYP)(GLuint )>(context->getProcAddress("glIsQuery"));
+ DeleteQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , const GLuint *)>(context->getProcAddress("glDeleteQueries"));
+ GenQueries = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLsizei , GLuint *)>(context->getProcAddress("glGenQueries"));
+
+ // Core in OpenGL >=3.2
+ GetInteger64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint64 *)>(context->getProcAddress("glGetInteger64v"));
+
+ // Core in OpenGL >=3.3 / ARB_timer_query
+ GetQueryObjectui64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64 *)>(context->getProcAddress("glGetQueryObjectui64v"));
+ GetQueryObjecti64v = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64 *)>(context->getProcAddress("glGetQueryObjecti64v"));
+ QueryCounter = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum )>(context->getProcAddress("glQueryCounter"));
+ }
+
+ inline void glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint *params)
+ {
+ GetQueryObjectuiv(id, pname, params);
+ }
+
+ inline void glGetQueryObjectiv(GLuint id, GLenum pname, GLint *params)
+ {
+ GetQueryObjectiv(id, pname, params);
+ }
+
+ inline void glGetQueryiv(GLenum target, GLenum pname, GLint *params)
+ {
+ GetQueryiv(target, pname, params);
+ }
+
+ inline void glEndQuery(GLenum target)
+ {
+ EndQuery(target);
+ }
+
+ inline void glBeginQuery(GLenum target, GLuint id)
+ {
+ BeginQuery(target, id);
+ }
+
+ inline GLboolean glIsQuery(GLuint id)
+ {
+ return IsQuery(id);
+ }
+
+ inline void glDeleteQueries(GLsizei n, const GLuint *ids)
+ {
+ DeleteQueries(n, ids);
+ }
+
+ inline void glGenQueries(GLsizei n, GLuint *ids)
+ {
+ GenQueries(n, ids);
+ }
+
+ inline void glGetInteger64v(GLenum pname, GLint64 *params)
+ {
+ GetInteger64v(pname, params);
+ }
+
+ inline void glGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 *params)
+ {
+ GetQueryObjectui64v(id, pname, params);
+ }
+
+ inline void glGetQueryObjecti64v(GLuint id, GLenum pname, GLint64 *params)
+ {
+ GetQueryObjecti64v(id, pname, params);
+ }
+
+ inline void glQueryCounter(GLuint id, GLenum target)
+ {
+ QueryCounter(id, target);
+ }
+
+private:
+ // Core in OpenGL >=1.5
+ void (QOPENGLF_APIENTRYP GetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params);
+ void (QOPENGLF_APIENTRYP GetQueryObjectiv)(GLuint id, GLenum pname, GLint *params);
+ void (QOPENGLF_APIENTRYP GetQueryiv)(GLenum target, GLenum pname, GLint *params);
+ void (QOPENGLF_APIENTRYP EndQuery)(GLenum target);
+ void (QOPENGLF_APIENTRYP BeginQuery)(GLenum target, GLuint id);
+ GLboolean (QOPENGLF_APIENTRYP IsQuery)(GLuint id);
+ void (QOPENGLF_APIENTRYP DeleteQueries)(GLsizei n, const GLuint *ids);
+ void (QOPENGLF_APIENTRYP GenQueries)(GLsizei n, GLuint *ids);
+
+ // Core in OpenGL >=3.2
+ void (QOPENGLF_APIENTRYP GetInteger64v)(GLenum pname, GLint64 *params);
+
+ // Core in OpenGL >=3.3 and provided by ARB_timer_query
+ void (QOPENGLF_APIENTRYP GetQueryObjectui64v)(GLuint id, GLenum pname, GLuint64 *params);
+ void (QOPENGLF_APIENTRYP GetQueryObjecti64v)(GLuint id, GLenum pname, GLint64 *params);
+ void (QOPENGLF_APIENTRYP QueryCounter)(GLuint id, GLenum target);
+};
+
+QT_END_NAMESPACE
+
+#endif
+
+#endif // QOPENGLQUERYHELPER_P_H
diff --git a/src/opengl/gl2paintengineex/qglshadercache_p.h b/src/opengl/qopenglshadercache_p.h
index 4204e3e256..88efa34216 100644
--- a/src/opengl/gl2paintengineex/qglshadercache_p.h
+++ b/src/opengl/qopenglshadercache_p.h
@@ -48,16 +48,16 @@
// We mean it.
//
-#ifndef QGLSHADERCACHE_P_H
-#define QGLSHADERCACHE_P_H
+#ifndef QOPENGLSHADERCACHE_P_H
+#define QOPENGLSHADERCACHE_P_H
-#include <QtCore/qglobal.h>
+#include <QtOpenGL/qtopenglglobal.h>
QT_BEGIN_NAMESPACE
-class QGLShaderProgram;
-class QGLContext;
+class QOpenGLShaderProgram;
+class QOpenGLContext;
class CachedShader
{
@@ -70,12 +70,12 @@ public:
return false;
}
- inline bool load(QGLShaderProgram *, const QGLContext *)
+ inline bool load(QOpenGLShaderProgram *, QOpenGLContext *)
{
return false;
}
- inline bool store(QGLShaderProgram *, const QGLContext *)
+ inline bool store(QOpenGLShaderProgram *, QOpenGLContext *)
{
return false;
}
diff --git a/src/opengl/qopengltexture.cpp b/src/opengl/qopengltexture.cpp
new file mode 100644
index 0000000000..49ebdfbec2
--- /dev/null
+++ b/src/opengl/qopengltexture.cpp
@@ -0,0 +1,4989 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengltexture.h"
+#include "qopengltexture_p.h"
+#include "qopengltexturehelper_p.h"
+#include "qopenglfunctions.h"
+#include <QtGui/qcolor.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtCore/qdebug.h>
+#include <private/qobject_p.h>
+#include <private/qopenglcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+//this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value
+#if !defined(GL_TEXTURE_WRAP_R)
+ #define GL_TEXTURE_WRAP_R 0x8072
+#endif
+
+QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,
+ QOpenGLTexture *qq)
+ : q_ptr(qq),
+ context(nullptr),
+ target(textureTarget),
+ textureId(0),
+ format(QOpenGLTexture::NoFormat),
+ formatClass(QOpenGLTexture::NoFormatClass),
+ requestedMipLevels(1),
+ mipLevels(-1),
+ layers(1),
+ faces(1),
+ samples(0),
+ fixedSamplePositions(true),
+ baseLevel(0),
+ maxLevel(1000),
+ depthStencilMode(QOpenGLTexture::DepthMode),
+ comparisonFunction(QOpenGLTexture::CompareLessEqual),
+ comparisonMode(QOpenGLTexture::CompareNone),
+ minFilter(QOpenGLTexture::Nearest),
+ magFilter(QOpenGLTexture::Nearest),
+ maxAnisotropy(1.0f),
+ minLevelOfDetail(-1000.0f),
+ maxLevelOfDetail(1000.0f),
+ levelOfDetailBias(0.0f),
+ textureView(false),
+ autoGenerateMipMaps(true),
+ storageAllocated(false),
+ texFuncs(nullptr),
+ functions(nullptr)
+{
+ dimensions[0] = dimensions[1] = dimensions[2] = 1;
+
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ bindingTarget = QOpenGLTexture::BindingTarget1D;
+ break;
+ case QOpenGLTexture::Target1DArray:
+ bindingTarget = QOpenGLTexture::BindingTarget1DArray;
+ break;
+ case QOpenGLTexture::Target2D:
+ bindingTarget = QOpenGLTexture::BindingTarget2D;
+ break;
+ case QOpenGLTexture::Target2DArray:
+ bindingTarget = QOpenGLTexture::BindingTarget2DArray;
+ break;
+ case QOpenGLTexture::Target3D:
+ bindingTarget = QOpenGLTexture::BindingTarget3D;
+ break;
+ case QOpenGLTexture::TargetCubeMap:
+ bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
+ faces = 6;
+ break;
+ case QOpenGLTexture::TargetCubeMapArray:
+ bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
+ faces = 6;
+ break;
+ case QOpenGLTexture::Target2DMultisample:
+ bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
+ break;
+ case QOpenGLTexture::Target2DMultisampleArray:
+ bindingTarget = QOpenGLTexture::BindingTarget2DMultisampleArray;
+ break;
+ case QOpenGLTexture::TargetRectangle:
+ bindingTarget = QOpenGLTexture::BindingTargetRectangle;
+ break;
+ case QOpenGLTexture::TargetBuffer:
+ bindingTarget = QOpenGLTexture::BindingTargetBuffer;
+ break;
+ }
+
+ swizzleMask[0] = QOpenGLTexture::RedValue;
+ swizzleMask[1] = QOpenGLTexture::GreenValue;
+ swizzleMask[2] = QOpenGLTexture::BlueValue;
+ swizzleMask[3] = QOpenGLTexture::AlphaValue;
+
+ wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
+ ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
+}
+
+QOpenGLTexturePrivate::~QOpenGLTexturePrivate()
+{
+ destroy();
+}
+
+void QOpenGLTexturePrivate::initializeOpenGLFunctions()
+{
+ // If we already have a functions object, there is nothing to do
+ if (texFuncs)
+ return;
+
+ // See if the context already has a suitable resource we can use.
+ // If not create a functions object and add it to the context in case
+ // others wish to use it too
+ texFuncs = context->textureFunctions();
+ if (!texFuncs) {
+ texFuncs = new QOpenGLTextureHelper(context);
+ auto *funcs = texFuncs; // lets us capture by pointer value below
+ context->setTextureFunctions(funcs, [funcs] { delete funcs; });
+ }
+}
+
+bool QOpenGLTexturePrivate::create()
+{
+ if (textureId != 0)
+ return true;
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("Requires a valid current OpenGL context.\n"
+ "Texture has not been created");
+ return false;
+ }
+ context = ctx;
+ functions = ctx->functions();
+
+ // Resolve any functions we will need based upon context version and create the texture
+ initializeOpenGLFunctions();
+
+ // What features do we have?
+ QOpenGLTexture::Feature feature = QOpenGLTexture::ImmutableStorage;
+ while (feature != QOpenGLTexture::MaxFeatureFlag) {
+ if (QOpenGLTexture::hasFeature(feature))
+ features |= feature;
+ feature = static_cast<QOpenGLTexture::Feature>(feature << 1);
+ }
+
+ functions->glGenTextures(1, &textureId);
+ return textureId != 0;
+}
+
+void QOpenGLTexturePrivate::destroy()
+{
+ if (!textureId) {
+ // not created or already destroyed
+ return;
+ }
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext) {
+ qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n"
+ "Texture has not been destroyed");
+ return;
+ }
+ if (!QOpenGLContext::areSharing(currentContext, context)) {
+
+ qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p"
+ " is not shared with current context %p.\n"
+ "Texture has not been destroyed",
+ static_cast<const void *>(context),
+ static_cast<const void *>(currentContext));
+ return;
+ }
+
+ functions->glDeleteTextures(1, &textureId);
+
+ context = nullptr;
+ functions = nullptr;
+ textureId = 0;
+ format = QOpenGLTexture::NoFormat;
+ formatClass = QOpenGLTexture::NoFormatClass;
+ requestedMipLevels = 1;
+ mipLevels = -1;
+ layers = 1;
+ faces = 1;
+ samples = 0;
+ fixedSamplePositions = true,
+ baseLevel = 0;
+ maxLevel = 1000;
+ depthStencilMode = QOpenGLTexture::DepthMode;
+ minFilter = QOpenGLTexture::Nearest;
+ magFilter = QOpenGLTexture::Nearest;
+ maxAnisotropy = 1.0f;
+ minLevelOfDetail = -1000.0f;
+ maxLevelOfDetail = 1000.0f;
+ levelOfDetailBias = 0.0f;
+ textureView = false;
+ autoGenerateMipMaps = true;
+ storageAllocated = false;
+ texFuncs = nullptr;
+
+ swizzleMask[0] = QOpenGLTexture::RedValue;
+ swizzleMask[1] = QOpenGLTexture::GreenValue;
+ swizzleMask[2] = QOpenGLTexture::BlueValue;
+ swizzleMask[3] = QOpenGLTexture::AlphaValue;
+
+ wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
+ ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
+}
+
+void QOpenGLTexturePrivate::bind()
+{
+ functions->glBindTexture(target, textureId);
+}
+
+void QOpenGLTexturePrivate::bind(uint unit, QOpenGLTexture::TextureUnitReset reset)
+{
+ GLint oldTextureUnit = 0;
+ if (reset == QOpenGLTexture::ResetTextureUnit)
+ functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
+
+ texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
+ functions->glBindTexture(target, textureId);
+
+ if (reset == QOpenGLTexture::ResetTextureUnit)
+ texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
+}
+
+void QOpenGLTexturePrivate::release()
+{
+ functions->glBindTexture(target, 0);
+}
+
+void QOpenGLTexturePrivate::release(uint unit, QOpenGLTexture::TextureUnitReset reset)
+{
+ GLint oldTextureUnit = 0;
+ if (reset == QOpenGLTexture::ResetTextureUnit)
+ functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
+
+ texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
+ functions->glBindTexture(target, 0);
+
+ if (reset == QOpenGLTexture::ResetTextureUnit)
+ texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
+}
+
+bool QOpenGLTexturePrivate::isBound() const
+{
+ GLint boundTextureId = 0;
+ functions->glGetIntegerv(bindingTarget, &boundTextureId);
+ return (static_cast<GLuint>(boundTextureId) == textureId);
+}
+
+bool QOpenGLTexturePrivate::isBound(uint unit) const
+{
+ GLint oldTextureUnit = 0;
+ functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
+
+ GLint boundTextureId = 0;
+ texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
+ functions->glGetIntegerv(bindingTarget, &boundTextureId);
+ bool result = (static_cast<GLuint>(boundTextureId) == textureId);
+
+ texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
+ return result;
+}
+
+int QOpenGLTexturePrivate::evaluateMipLevels() const
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ return qMin(maximumMipLevelCount(), qMax(1, requestedMipLevels));
+
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetBuffer:
+ default:
+ return 1;
+ }
+}
+
+static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+ return false;
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ case QOpenGLTexture::RGB9E5:
+ case QOpenGLTexture::RG11B10F:
+ case QOpenGLTexture::RG3B2:
+ case QOpenGLTexture::R5G6B5:
+ case QOpenGLTexture::RGB5A1:
+ case QOpenGLTexture::RGBA4:
+ case QOpenGLTexture::RGB10A2:
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+
+ case QOpenGLTexture::D24S8:
+ case QOpenGLTexture::D32FS8X24:
+
+ case QOpenGLTexture::S8:
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGBA_ASTC_4x4:
+ case QOpenGLTexture::RGBA_ASTC_5x4:
+ case QOpenGLTexture::RGBA_ASTC_5x5:
+ case QOpenGLTexture::RGBA_ASTC_6x5:
+ case QOpenGLTexture::RGBA_ASTC_6x6:
+ case QOpenGLTexture::RGBA_ASTC_8x5:
+ case QOpenGLTexture::RGBA_ASTC_8x6:
+ case QOpenGLTexture::RGBA_ASTC_8x8:
+ case QOpenGLTexture::RGBA_ASTC_10x5:
+ case QOpenGLTexture::RGBA_ASTC_10x6:
+ case QOpenGLTexture::RGBA_ASTC_10x8:
+ case QOpenGLTexture::RGBA_ASTC_10x10:
+ case QOpenGLTexture::RGBA_ASTC_12x10:
+ case QOpenGLTexture::RGBA_ASTC_12x12:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
+ return true;
+
+ case QOpenGLTexture::RGB8_ETC1:
+ return false;
+
+ case QOpenGLTexture::DepthFormat:
+ case QOpenGLTexture::AlphaFormat:
+
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+
+ case QOpenGLTexture::LuminanceFormat:
+
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return false;
+ }
+
+ Q_UNREACHABLE();
+ return false;
+}
+
+static bool isTextureTargetMultisample(QOpenGLTexture::Target target)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ return false;
+
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ return true;
+
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::TargetBuffer:
+ return false;
+ }
+
+ Q_UNREACHABLE();
+ return false;
+}
+
+bool QOpenGLTexturePrivate::isUsingImmutableStorage() const
+{
+ // Use immutable storage whenever possible, falling back to mutable
+ // Note that if multisample textures are not supported at all, we'll still fail into
+ // the mutable storage allocation
+ return isSizedTextureFormat(format)
+ && (isTextureTargetMultisample(target)
+ ? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
+ : features.testFlag(QOpenGLTexture::ImmutableStorage));
+}
+
+void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
+{
+ // Resolve the actual number of mipmap levels we can use
+ mipLevels = evaluateMipLevels();
+
+ if (isUsingImmutableStorage())
+ allocateImmutableStorage();
+ else
+ allocateMutableStorage(pixelFormat, pixelType);
+}
+
+static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+ return QOpenGLTexture::NoSourceFormat;
+
+ case QOpenGLTexture::R8_UNorm:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG8_UNorm:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB8_UNorm:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA8_UNorm:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R16_UNorm:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG16_UNorm:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB16_UNorm:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA16_UNorm:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R8_SNorm:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG8_SNorm:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB8_SNorm:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA8_SNorm:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R16_SNorm:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG16_SNorm:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB16_SNorm:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA16_SNorm:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R8U:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG8U:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB8U:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA8U:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R16U:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG16U:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB16U:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA16U:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R32U:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG32U:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB32U:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA32U:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R8I:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG8I:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB8I:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA8I:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R16I:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG16I:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB16I:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA16I:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R32I:
+ return QOpenGLTexture::Red_Integer;
+
+ case QOpenGLTexture::RG32I:
+ return QOpenGLTexture::RG_Integer;
+
+ case QOpenGLTexture::RGB32I:
+ return QOpenGLTexture::RGB_Integer;
+
+ case QOpenGLTexture::RGBA32I:
+ return QOpenGLTexture::RGBA_Integer;
+
+ case QOpenGLTexture::R16F:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG16F:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB16F:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA16F:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R32F:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG32F:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB32F:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBA32F:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::RGB9E5:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RG11B10F:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RG3B2:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::R5G6B5:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGB5A1:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::RGBA4:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::RGB10A2:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+ return QOpenGLTexture::Depth;
+
+ case QOpenGLTexture::D24S8:
+ case QOpenGLTexture::D32FS8X24:
+ return QOpenGLTexture::DepthStencil;
+
+ case QOpenGLTexture::S8:
+ return QOpenGLTexture::Stencil;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::RGB8_ETC1:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ return QOpenGLTexture::Red;
+
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ return QOpenGLTexture::RG;
+
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::RGBA_ASTC_4x4:
+ case QOpenGLTexture::RGBA_ASTC_5x4:
+ case QOpenGLTexture::RGBA_ASTC_5x5:
+ case QOpenGLTexture::RGBA_ASTC_6x5:
+ case QOpenGLTexture::RGBA_ASTC_6x6:
+ case QOpenGLTexture::RGBA_ASTC_8x5:
+ case QOpenGLTexture::RGBA_ASTC_8x6:
+ case QOpenGLTexture::RGBA_ASTC_8x8:
+ case QOpenGLTexture::RGBA_ASTC_10x5:
+ case QOpenGLTexture::RGBA_ASTC_10x6:
+ case QOpenGLTexture::RGBA_ASTC_10x8:
+ case QOpenGLTexture::RGBA_ASTC_10x10:
+ case QOpenGLTexture::RGBA_ASTC_12x10:
+ case QOpenGLTexture::RGBA_ASTC_12x12:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::DepthFormat:
+ return QOpenGLTexture::Depth;
+
+ case QOpenGLTexture::AlphaFormat:
+ return QOpenGLTexture::Alpha;
+
+ case QOpenGLTexture::RGBFormat:
+ return QOpenGLTexture::RGB;
+
+ case QOpenGLTexture::RGBAFormat:
+ return QOpenGLTexture::RGBA;
+
+ case QOpenGLTexture::LuminanceFormat:
+ return QOpenGLTexture::Luminance;
+
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return QOpenGLTexture::LuminanceAlpha;
+ }
+
+ Q_UNREACHABLE();
+ return QOpenGLTexture::NoSourceFormat;
+}
+
+static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+ return QOpenGLTexture::NoPixelType;
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ return QOpenGLTexture::Int8;
+
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ return QOpenGLTexture::Int8;
+
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ return QOpenGLTexture::Float16;
+
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ return QOpenGLTexture::Float32;
+
+ case QOpenGLTexture::RGB9E5:
+ return QOpenGLTexture::UInt16_RGB5A1_Rev;
+
+ case QOpenGLTexture::RG11B10F:
+ return QOpenGLTexture::UInt32_RG11B10F;
+
+ case QOpenGLTexture::RG3B2:
+ return QOpenGLTexture::UInt8_RG3B2;
+
+ case QOpenGLTexture::R5G6B5:
+ return QOpenGLTexture::UInt16_R5G6B5;
+
+ case QOpenGLTexture::RGB5A1:
+ return QOpenGLTexture::UInt16_RGB5A1;
+
+ case QOpenGLTexture::RGBA4:
+ return QOpenGLTexture::UInt16_RGBA4;
+
+ case QOpenGLTexture::RGB10A2:
+ return QOpenGLTexture::UInt32_RGB10A2;
+
+ case QOpenGLTexture::D16:
+ return QOpenGLTexture::UInt16;
+
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ return QOpenGLTexture::UInt32;
+
+ case QOpenGLTexture::D32F:
+ return QOpenGLTexture::Float32;
+
+ case QOpenGLTexture::D24S8:
+ return QOpenGLTexture::UInt32_D24S8;
+
+ case QOpenGLTexture::D32FS8X24:
+ return QOpenGLTexture::Float32_D32_UInt32_S8_X24;
+
+ case QOpenGLTexture::S8:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
+ case QOpenGLTexture::RGBA_ASTC_4x4:
+ case QOpenGLTexture::RGBA_ASTC_5x4:
+ case QOpenGLTexture::RGBA_ASTC_5x5:
+ case QOpenGLTexture::RGBA_ASTC_6x5:
+ case QOpenGLTexture::RGBA_ASTC_6x6:
+ case QOpenGLTexture::RGBA_ASTC_8x5:
+ case QOpenGLTexture::RGBA_ASTC_8x6:
+ case QOpenGLTexture::RGBA_ASTC_8x8:
+ case QOpenGLTexture::RGBA_ASTC_10x5:
+ case QOpenGLTexture::RGBA_ASTC_10x6:
+ case QOpenGLTexture::RGBA_ASTC_10x8:
+ case QOpenGLTexture::RGBA_ASTC_10x10:
+ case QOpenGLTexture::RGBA_ASTC_12x10:
+ case QOpenGLTexture::RGBA_ASTC_12x12:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
+ return QOpenGLTexture::UInt8;
+
+ case QOpenGLTexture::DepthFormat:
+ return QOpenGLTexture::UInt32;
+
+ case QOpenGLTexture::AlphaFormat:
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+ case QOpenGLTexture::LuminanceFormat:
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return QOpenGLTexture::UInt8;
+ }
+
+ Q_UNREACHABLE();
+ return QOpenGLTexture::NoPixelType;
+}
+
+static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
+{
+ switch (internalFormat) {
+ case QOpenGLTexture::NoFormat:
+
+ case QOpenGLTexture::R8_UNorm:
+ case QOpenGLTexture::RG8_UNorm:
+ case QOpenGLTexture::RGB8_UNorm:
+ case QOpenGLTexture::RGBA8_UNorm:
+ case QOpenGLTexture::R16_UNorm:
+ case QOpenGLTexture::RG16_UNorm:
+ case QOpenGLTexture::RGB16_UNorm:
+ case QOpenGLTexture::RGBA16_UNorm:
+ case QOpenGLTexture::R8_SNorm:
+ case QOpenGLTexture::RG8_SNorm:
+ case QOpenGLTexture::RGB8_SNorm:
+ case QOpenGLTexture::RGBA8_SNorm:
+ case QOpenGLTexture::R16_SNorm:
+ case QOpenGLTexture::RG16_SNorm:
+ case QOpenGLTexture::RGB16_SNorm:
+ case QOpenGLTexture::RGBA16_SNorm:
+ case QOpenGLTexture::R8U:
+ case QOpenGLTexture::RG8U:
+ case QOpenGLTexture::RGB8U:
+ case QOpenGLTexture::RGBA8U:
+ case QOpenGLTexture::R16U:
+ case QOpenGLTexture::RG16U:
+ case QOpenGLTexture::RGB16U:
+ case QOpenGLTexture::RGBA16U:
+ case QOpenGLTexture::R32U:
+ case QOpenGLTexture::RG32U:
+ case QOpenGLTexture::RGB32U:
+ case QOpenGLTexture::RGBA32U:
+ case QOpenGLTexture::R8I:
+ case QOpenGLTexture::RG8I:
+ case QOpenGLTexture::RGB8I:
+ case QOpenGLTexture::RGBA8I:
+ case QOpenGLTexture::R16I:
+ case QOpenGLTexture::RG16I:
+ case QOpenGLTexture::RGB16I:
+ case QOpenGLTexture::RGBA16I:
+ case QOpenGLTexture::R32I:
+ case QOpenGLTexture::RG32I:
+ case QOpenGLTexture::RGB32I:
+ case QOpenGLTexture::RGBA32I:
+ case QOpenGLTexture::R16F:
+ case QOpenGLTexture::RG16F:
+ case QOpenGLTexture::RGB16F:
+ case QOpenGLTexture::RGBA16F:
+ case QOpenGLTexture::R32F:
+ case QOpenGLTexture::RG32F:
+ case QOpenGLTexture::RGB32F:
+ case QOpenGLTexture::RGBA32F:
+ case QOpenGLTexture::RGB9E5:
+ case QOpenGLTexture::RG11B10F:
+ case QOpenGLTexture::RG3B2:
+ case QOpenGLTexture::R5G6B5:
+ case QOpenGLTexture::RGB5A1:
+ case QOpenGLTexture::RGBA4:
+ case QOpenGLTexture::RGB10A2:
+
+ case QOpenGLTexture::D16:
+ case QOpenGLTexture::D24:
+ case QOpenGLTexture::D32:
+ case QOpenGLTexture::D32F:
+
+ case QOpenGLTexture::D24S8:
+ case QOpenGLTexture::D32FS8X24:
+
+ case QOpenGLTexture::S8:
+ return false;
+
+ case QOpenGLTexture::RGB_DXT1:
+ case QOpenGLTexture::RGBA_DXT1:
+ case QOpenGLTexture::RGBA_DXT3:
+ case QOpenGLTexture::RGBA_DXT5:
+ case QOpenGLTexture::R_ATI1N_UNorm:
+ case QOpenGLTexture::R_ATI1N_SNorm:
+ case QOpenGLTexture::RG_ATI2N_UNorm:
+ case QOpenGLTexture::RG_ATI2N_SNorm:
+ case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
+ case QOpenGLTexture::RGB_BP_UNorm:
+ case QOpenGLTexture::SRGB8:
+ case QOpenGLTexture::SRGB8_Alpha8:
+ case QOpenGLTexture::SRGB_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT1:
+ case QOpenGLTexture::SRGB_Alpha_DXT3:
+ case QOpenGLTexture::SRGB_Alpha_DXT5:
+ case QOpenGLTexture::SRGB_BP_UNorm:
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
+ case QOpenGLTexture::RGBA_ASTC_4x4:
+ case QOpenGLTexture::RGBA_ASTC_5x4:
+ case QOpenGLTexture::RGBA_ASTC_5x5:
+ case QOpenGLTexture::RGBA_ASTC_6x5:
+ case QOpenGLTexture::RGBA_ASTC_6x6:
+ case QOpenGLTexture::RGBA_ASTC_8x5:
+ case QOpenGLTexture::RGBA_ASTC_8x6:
+ case QOpenGLTexture::RGBA_ASTC_8x8:
+ case QOpenGLTexture::RGBA_ASTC_10x5:
+ case QOpenGLTexture::RGBA_ASTC_10x6:
+ case QOpenGLTexture::RGBA_ASTC_10x8:
+ case QOpenGLTexture::RGBA_ASTC_10x10:
+ case QOpenGLTexture::RGBA_ASTC_12x10:
+ case QOpenGLTexture::RGBA_ASTC_12x12:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
+ return true;
+
+ case QOpenGLTexture::DepthFormat:
+ case QOpenGLTexture::AlphaFormat:
+ case QOpenGLTexture::RGBFormat:
+ case QOpenGLTexture::RGBAFormat:
+ case QOpenGLTexture::LuminanceFormat:
+ case QOpenGLTexture::LuminanceAlphaFormat:
+ return false;
+ }
+
+ Q_UNREACHABLE();
+ return false;
+}
+
+void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
+{
+ // There is no way to allocate mutable storage for compressed textures in in
+ // versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs
+ // do not mandate accepting null data pointers for glCompressedTexImage*D,
+ // unlike glTexImage*D (which in turn does not accept compressed formats).
+ if (isCompressedFormat(format)) {
+ storageAllocated = true;
+ return;
+ }
+
+ switch (target) {
+ case QOpenGLTexture::TargetBuffer:
+ // Buffer textures get their storage from an external OpenGL buffer
+ qWarning("Buffer textures do not allocate storage");
+ return;
+
+ case QOpenGLTexture::Target1D:
+ if (features.testFlag(QOpenGLTexture::Texture1D)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ 0,
+ pixelFormat, pixelType, nullptr);
+ } else {
+ qWarning("1D textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ if (features.testFlag(QOpenGLTexture::Texture1D)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ layers,
+ 0,
+ pixelFormat, pixelType, nullptr);
+ } else {
+ qWarning("1D array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::TargetRectangle:
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ mipLevelSize(level, dimensions[1]),
+ 0,
+ pixelFormat, pixelType, nullptr);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap: {
+ // Cubemaps are the odd one out. We have to allocate storage for each
+ // face and miplevel using the special cubemap face targets rather than
+ // GL_TARGET_CUBEMAP.
+ const QOpenGLTexture::CubeMapFace faceTargets[] = {
+ QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX,
+ QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY,
+ QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ
+ };
+
+ for (int faceTarget = 0; faceTarget < 6; ++faceTarget) {
+ for (int level = 0; level < mipLevels; ++level) {
+ texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget,
+ level, format,
+ mipLevelSize(level, dimensions[0]),
+ mipLevelSize(level, dimensions[1]),
+ 0,
+ pixelFormat, pixelType, nullptr);
+ }
+ }
+ break;
+ }
+
+ case QOpenGLTexture::Target2DArray:
+ if (features.testFlag(QOpenGLTexture::TextureArrays)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ mipLevelSize(level, dimensions[1]),
+ layers,
+ 0,
+ pixelFormat, pixelType, nullptr);
+ } else {
+ qWarning("Array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray:
+ // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
+ if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ mipLevelSize(level, dimensions[1]),
+ 6 * layers,
+ 0,
+ pixelFormat, pixelType, nullptr);
+ } else {
+ qWarning("Cubemap Array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target3D:
+ if (features.testFlag(QOpenGLTexture::Texture3D)) {
+ for (int level = 0; level < mipLevels; ++level)
+ texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
+ mipLevelSize(level, dimensions[0]),
+ mipLevelSize(level, dimensions[1]),
+ mipLevelSize(level, dimensions[2]),
+ 0,
+ pixelFormat, pixelType, nullptr);
+ } else {
+ qWarning("3D textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ if (features.testFlag(QOpenGLTexture::TextureMultisample)) {
+ texFuncs->glTextureImage2DMultisample(textureId, target, bindingTarget, samples, format,
+ dimensions[0], dimensions[1],
+ fixedSamplePositions);
+ } else {
+ qWarning("Multisample textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2DMultisampleArray:
+ if (features.testFlag(QOpenGLTexture::TextureMultisample)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
+ texFuncs->glTextureImage3DMultisample(textureId, target, bindingTarget, samples, format,
+ dimensions[0], dimensions[1], layers,
+ fixedSamplePositions);
+ } else {
+ qWarning("Multisample array textures are not supported");
+ return;
+ }
+ break;
+ }
+
+ storageAllocated = true;
+}
+
+void QOpenGLTexturePrivate::allocateImmutableStorage()
+{
+ switch (target) {
+ case QOpenGLTexture::TargetBuffer:
+ // Buffer textures get their storage from an external OpenGL buffer
+ qWarning("Buffer textures do not allocate storage");
+ return;
+
+ case QOpenGLTexture::Target1D:
+ if (features.testFlag(QOpenGLTexture::Texture1D)) {
+ texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0]);
+ } else {
+ qWarning("1D textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ if (features.testFlag(QOpenGLTexture::Texture1D)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
+ texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0], layers);
+ } else {
+ qWarning("1D array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetRectangle:
+ texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0], dimensions[1]);
+ break;
+
+ case QOpenGLTexture::Target2DArray:
+ if (features.testFlag(QOpenGLTexture::TextureArrays)) {
+ texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0], dimensions[1], layers);
+ } else {
+ qWarning("Array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray:
+ // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
+ if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
+ texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0], dimensions[1], 6 * layers);
+ } else {
+ qWarning("Cubemap Array textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target3D:
+ if (features.testFlag(QOpenGLTexture::Texture3D)) {
+ texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
+ dimensions[0], dimensions[1], dimensions[2]);
+ } else {
+ qWarning("3D textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) {
+ texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format,
+ dimensions[0], dimensions[1],
+ fixedSamplePositions);
+ } else {
+ qWarning("Multisample textures are not supported");
+ return;
+ }
+ break;
+
+ case QOpenGLTexture::Target2DMultisampleArray:
+ if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
+ && features.testFlag(QOpenGLTexture::TextureArrays)) {
+ texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format,
+ dimensions[0], dimensions[1], layers,
+ fixedSamplePositions);
+ } else {
+ qWarning("Multisample array textures are not supported");
+ return;
+ }
+ break;
+ }
+
+ storageAllocated = true;
+}
+
+void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
+ 0, mipLevelSize( mipLevel, dimensions[0] ),
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ Q_UNUSED(cubeFace);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DArray:
+ Q_UNUSED(cubeFace);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ mipLevelSize(mipLevel, dimensions[2]),
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ Q_UNUSED(layer);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray: {
+ int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
+ int layerFace = 6 * layer + faceIndex;
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layerFace,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+ }
+
+ case QOpenGLTexture::TargetRectangle:
+ Q_UNUSED(mipLevel);
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
+ 0, 0,
+ dimensions[0],
+ dimensions[1],
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetBuffer:
+ // We don't upload pixel data for these targets
+ qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
+ break;
+ }
+
+ // If requested perform automatic mip map generation
+ if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
+ Q_Q(QOpenGLTexture);
+ q->generateMipMaps();
+ }
+}
+
+void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
+ int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(yOffset);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
+ xOffset, width,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(yOffset);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ xOffset, layer,
+ width,
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DArray:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, layer,
+ width, height, layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, zOffset,
+ width, height, depth,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ Q_UNUSED(layer);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray: {
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
+ int layerFace = 6 * layer + faceIndex;
+ texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ xOffset, yOffset, layerFace,
+ width, height,
+ layerCount,
+ sourceFormat, sourceType, data, options);
+ break;
+ }
+
+ case QOpenGLTexture::TargetRectangle:
+ Q_UNUSED(mipLevel);
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ Q_UNUSED(zOffset);
+ Q_UNUSED(depth);
+ texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
+ xOffset, yOffset,
+ width, height,
+ sourceFormat, sourceType, data, options);
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetBuffer:
+ // We don't upload pixel data for these targets
+ qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
+ break;
+ }
+
+ // If requested perform automatic mip map generation
+ if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
+ Q_Q(QOpenGLTexture);
+ q->generateMipMaps();
+ }
+}
+
+
+void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount,
+ QOpenGLTexture::CubeMapFace cubeFace,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ if (!isCompressedFormat(format)) {
+ qWarning("Cannot set compressed data for non-compressed format 0x%x", format);
+ return;
+ }
+
+ const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op?
+
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
+ 0, mipLevelSize( mipLevel, dimensions[0] ),
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::Target1DArray:
+ Q_UNUSED(cubeFace);
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ layerCount,
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::Target2D:
+ Q_UNUSED(layer);
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::Target2DArray:
+ Q_UNUSED(cubeFace);
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ layerCount,
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::Target3D:
+ Q_UNUSED(cubeFace);
+ Q_UNUSED(layerCount);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ mipLevelSize(mipLevel, dimensions[2]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layer,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ mipLevelSize(mipLevel, dimensions[2]),
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ Q_UNUSED(layer);
+ Q_UNUSED(layerCount);
+ if (needsFullSpec) {
+ texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ format,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ 0, dataSize, data, options);
+ } else {
+ texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
+ 0, 0,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ format, dataSize, data, options);
+ }
+ break;
+
+ case QOpenGLTexture::TargetCubeMapArray: {
+ int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
+ int layerFace = 6 * layer + faceIndex;
+ if (!needsFullSpec) {
+ texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
+ 0, 0, layerFace,
+ mipLevelSize(mipLevel, dimensions[0]),
+ mipLevelSize(mipLevel, dimensions[1]),
+ layerCount,
+ format, dataSize, data, options);
+ }
+ break;
+ }
+
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetBuffer:
+ // We don't upload pixel data for these targets
+ qWarning("QOpenGLTexture::setCompressedData(): Texture target does not support pixel data upload");
+ break;
+ }
+
+ // If requested perform automatic mip map generation
+ if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
+ Q_Q(QOpenGLTexture);
+ q->generateMipMaps();
+ }
+}
+
+void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::WrapMode mode)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::TargetBuffer:
+ wrapModes[0] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetRectangle:
+ wrapModes[0] = wrapModes[1] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ wrapModes[0] = wrapModes[1] = wrapModes[2] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_R, mode);
+ break;
+ }
+}
+
+void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::TargetBuffer:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ wrapModes[0] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
+ break;
+
+ case QOpenGLTexture::DirectionT:
+ case QOpenGLTexture::DirectionR:
+ qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
+ break;
+ }
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetRectangle:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ wrapModes[0] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
+ break;
+
+ case QOpenGLTexture::DirectionT:
+ wrapModes[1] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
+ break;
+
+ case QOpenGLTexture::DirectionR:
+ qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
+ break;
+ }
+ break;
+
+ case QOpenGLTexture::Target3D:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ wrapModes[0] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
+ break;
+
+ case QOpenGLTexture::DirectionT:
+ wrapModes[1] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
+ break;
+
+ case QOpenGLTexture::DirectionR:
+ wrapModes[2] = mode;
+ texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
+ break;
+ }
+ break;
+ }
+}
+
+QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
+{
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::TargetBuffer:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ return wrapModes[0];
+
+ case QOpenGLTexture::DirectionT:
+ case QOpenGLTexture::DirectionR:
+ qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
+ return QOpenGLTexture::Repeat;
+ }
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ case QOpenGLTexture::TargetRectangle:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ return wrapModes[0];
+
+ case QOpenGLTexture::DirectionT:
+ return wrapModes[1];
+
+ case QOpenGLTexture::DirectionR:
+ qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
+ return QOpenGLTexture::Repeat;
+ }
+ break;
+
+ case QOpenGLTexture::Target3D:
+ switch (direction) {
+ case QOpenGLTexture::DirectionS:
+ return wrapModes[0];
+
+ case QOpenGLTexture::DirectionT:
+ return wrapModes[1];
+
+ case QOpenGLTexture::DirectionR:
+ return wrapModes[2];
+ }
+ break;
+ }
+ // Should never get here
+ Q_ASSERT(false);
+ return QOpenGLTexture::Repeat;
+}
+
+QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target viewTarget,
+ QOpenGLTexture::TextureFormat viewFormat,
+ int minimumMipmapLevel, int maximumMipmapLevel,
+ int minimumLayer, int maximumLayer) const
+{
+ // Do sanity checks - see http://www.opengl.org/wiki/GLAPI/glTextureView
+
+ // Check the targets are compatible
+ bool viewTargetCompatible = false;
+ switch (target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::Target1D
+ || viewTarget == QOpenGLTexture::Target1DArray);
+ break;
+
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2D
+ || viewTarget == QOpenGLTexture::Target2DArray);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::Target3D);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetCubeMap
+ || viewTarget == QOpenGLTexture::Target2D
+ || viewTarget == QOpenGLTexture::Target2DArray
+ || viewTarget == QOpenGLTexture::TargetCubeMapArray);
+ break;
+
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2DMultisample
+ || viewTarget == QOpenGLTexture::Target2DMultisampleArray);
+ break;
+
+ case QOpenGLTexture::TargetRectangle:
+ viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetRectangle);
+ break;
+
+ case QOpenGLTexture::TargetBuffer:
+ // Cannot be used with texture views
+ break;
+ }
+
+ if (!viewTargetCompatible) {
+ qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view targets");
+ return nullptr;
+ }
+
+ // Check the formats are compatible
+ bool viewFormatCompatible = false;
+ switch (formatClass) {
+ case QOpenGLTexture::NoFormatClass:
+ break;
+
+ case QOpenGLTexture::FormatClass_128Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA32F
+ || viewFormat == QOpenGLTexture::RGBA32U
+ || viewFormat == QOpenGLTexture::RGBA32I);
+ break;
+
+ case QOpenGLTexture::FormatClass_96Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB32F
+ || viewFormat == QOpenGLTexture::RGB32U
+ || viewFormat == QOpenGLTexture::RGB32I);
+ break;
+
+ case QOpenGLTexture::FormatClass_64Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA16F
+ || viewFormat == QOpenGLTexture::RG32F
+ || viewFormat == QOpenGLTexture::RGBA16U
+ || viewFormat == QOpenGLTexture::RG32U
+ || viewFormat == QOpenGLTexture::RGBA16I
+ || viewFormat == QOpenGLTexture::RG32I
+ || viewFormat == QOpenGLTexture::RGBA16_UNorm
+ || viewFormat == QOpenGLTexture::RGBA16_SNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_48Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB16_UNorm
+ || viewFormat == QOpenGLTexture::RGB16_SNorm
+ || viewFormat == QOpenGLTexture::RGB16F
+ || viewFormat == QOpenGLTexture::RGB16U
+ || viewFormat == QOpenGLTexture::RGB16I);
+ break;
+
+ case QOpenGLTexture::FormatClass_32Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RG16F
+ || viewFormat == QOpenGLTexture::RG11B10F
+ || viewFormat == QOpenGLTexture::R32F
+ || viewFormat == QOpenGLTexture::RGB10A2
+ || viewFormat == QOpenGLTexture::RGBA8U
+ || viewFormat == QOpenGLTexture::RG16U
+ || viewFormat == QOpenGLTexture::R32U
+ || viewFormat == QOpenGLTexture::RGBA8I
+ || viewFormat == QOpenGLTexture::RG16I
+ || viewFormat == QOpenGLTexture::R32I
+ || viewFormat == QOpenGLTexture::RGBA8_UNorm
+ || viewFormat == QOpenGLTexture::RG16_UNorm
+ || viewFormat == QOpenGLTexture::RGBA8_SNorm
+ || viewFormat == QOpenGLTexture::RG16_SNorm
+ || viewFormat == QOpenGLTexture::SRGB8_Alpha8
+ || viewFormat == QOpenGLTexture::RGB9E5);
+ break;
+
+ case QOpenGLTexture::FormatClass_24Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB8_UNorm
+ || viewFormat == QOpenGLTexture::RGB8_SNorm
+ || viewFormat == QOpenGLTexture::SRGB8
+ || viewFormat == QOpenGLTexture::RGB8U
+ || viewFormat == QOpenGLTexture::RGB8I);
+ break;
+
+ case QOpenGLTexture::FormatClass_16Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::R16F
+ || viewFormat == QOpenGLTexture::RG8U
+ || viewFormat == QOpenGLTexture::R16U
+ || viewFormat == QOpenGLTexture::RG8I
+ || viewFormat == QOpenGLTexture::R16I
+ || viewFormat == QOpenGLTexture::RG8_UNorm
+ || viewFormat == QOpenGLTexture::R16_UNorm
+ || viewFormat == QOpenGLTexture::RG8_SNorm
+ || viewFormat == QOpenGLTexture::R16_SNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_8Bit:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::R8U
+ || viewFormat == QOpenGLTexture::R8I
+ || viewFormat == QOpenGLTexture::R8_UNorm
+ || viewFormat == QOpenGLTexture::R8_SNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_RGTC1_R:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::R_ATI1N_UNorm
+ || viewFormat == QOpenGLTexture::R_ATI1N_SNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_RGTC2_RG:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RG_ATI2N_UNorm
+ || viewFormat == QOpenGLTexture::RG_ATI2N_SNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_BPTC_Unorm:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNorm
+ || viewFormat == QOpenGLTexture::SRGB_BP_UNorm);
+ break;
+
+ case QOpenGLTexture::FormatClass_BPTC_Float:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT
+ || viewFormat == QOpenGLTexture::RGB_BP_SIGNED_FLOAT);
+ break;
+
+ case QOpenGLTexture::FormatClass_S3TC_DXT1_RGB:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_DXT1
+ || viewFormat == QOpenGLTexture::SRGB_DXT1);
+ break;
+
+ case QOpenGLTexture::FormatClass_S3TC_DXT1_RGBA:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT1
+ || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT1);
+ break;
+
+ case QOpenGLTexture::FormatClass_S3TC_DXT3_RGBA:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT3
+ || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT3);
+ break;
+
+ case QOpenGLTexture::FormatClass_S3TC_DXT5_RGBA:
+ viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT5
+ || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT5);
+ break;
+
+ case QOpenGLTexture::FormatClass_Unique:
+ viewFormatCompatible = (viewFormat == format);
+ break;
+ }
+
+ if (!viewFormatCompatible) {
+ qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view formats");
+ return nullptr;
+ }
+
+
+ // Create a view
+ QOpenGLTexture *view = new QOpenGLTexture(viewTarget);
+ view->setFormat(viewFormat);
+ view->create();
+ view->d_ptr->textureView = true;
+ texFuncs->glTextureView(view->textureId(), viewTarget, textureId, viewFormat,
+ minimumMipmapLevel, maximumMipmapLevel - minimumMipmapLevel + 1,
+ minimumLayer, maximumLayer - minimumLayer + 1);
+ return view;
+}
+
+
+/*!
+ \class QOpenGLTexture
+ \inmodule QtGui
+ \since 5.2
+ \wrapper
+ \brief The QOpenGLTexture class encapsulates an OpenGL texture object.
+
+ QOpenGLTexture makes it easy to work with OpenGL textures and the myriad features
+ and targets that they offer depending upon the capabilities of your OpenGL implementation.
+
+ The typical usage pattern for QOpenGLTexture is
+ \list
+ \li Instantiate the object specifying the texture target type
+ \li Set properties that affect the storage requirements e.g. storage format, dimensions
+ \li Allocate the server-side storage
+ \li Optionally upload pixel data
+ \li Optionally set any additional properties e.g. filtering and border options
+ \li Render with texture or render to texture
+ \endlist
+
+ In the common case of simply using a QImage as the source of texture pixel data
+ most of the above steps are performed automatically.
+
+ \code
+ // Prepare texture
+ QOpenGLTexture *texture = new QOpenGLTexture(QImage(fileName).mirrored());
+ texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
+ texture->setMagnificationFilter(QOpenGLTexture::Linear);
+ ...
+ // Render with texture
+ texture->bind();
+ glDrawArrays(...);
+ \endcode
+
+ Note that the QImage is mirrored vertically to account for the fact that
+ OpenGL and QImage use opposite directions for the y axis. Another option
+ would be to transform your texture coordinates.
+*/
+
+/*!
+ \enum QOpenGLTexture::Filter
+ This enum defines the filtering parameters for a QOpenGLTexture object.
+ \value Nearest Equivalent to GL_NEAREST
+ \value Linear Equivalent to GL_LINEAR
+ \value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST
+ \value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR
+ \value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST
+ \value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR
+*/
+
+/*!
+ \enum QOpenGLTexture::Target
+ This enum defines the texture target of a QOpenGLTexture object.
+ For more information on creating array textures, see \l{Array Texture}.
+
+ \value Target1D A 1-dimensional texture.
+ Equivalent to GL_TEXTURE_1D.
+ \value Target1DArray An array of 1-dimensional textures.
+ Equivalent to GL_TEXTURE_1D_ARRAY
+ \value Target2D A 2-dimensional texture.
+ Equivalent to GL_TEXTURE_2D
+ \value Target2DArray An array of 2-dimensional textures.
+ Equivalent to GL_TEXTURE_2D_ARRAY
+ \value Target3D A 3-dimensional texture.
+ Equivalent to GL_TEXTURE_3D
+ \value TargetCubeMap A cubemap texture.
+ Equivalent to GL_TEXTURE_CUBE_MAP
+ \value TargetCubeMapArray An array of cubemap textures.
+ Equivalent to GL_TEXTURE_CUBE_MAP_ARRAY
+ \value Target2DMultisample A 2-dimensional texture with multisample support.
+ Equivalent to GL_TEXTURE_2D_MULTISAMPLE
+ \value Target2DMultisampleArray An array of 2-dimensional textures with multisample support.
+ Equivalent to GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+ \value TargetRectangle A rectangular 2-dimensional texture.
+ Equivalent to GL_TEXTURE_RECTANGLE
+ \value TargetBuffer A texture with data from an OpenGL buffer object.
+ Equivalent to GL_TEXTURE_BUFFER
+*/
+
+/*!
+ \enum QOpenGLTexture::BindingTarget
+ This enum defines the possible binding targets of texture units.
+
+ \value BindingTarget1D Equivalent to GL_TEXTURE_BINDING_1D
+ \value BindingTarget1DArray Equivalent to GL_TEXTURE_BINDING_1D_ARRAY
+ \value BindingTarget2D Equivalent to GL_TEXTURE_BINDING_2D
+ \value BindingTarget2DArray Equivalent to GL_TEXTURE_BINDING_2D_ARRAY
+ \value BindingTarget3D Equivalent to GL_TEXTURE_BINDING_3D
+ \value BindingTargetCubeMap Equivalent to GL_TEXTURE_BINDING_CUBE_MAP
+ \value BindingTargetCubeMapArray Equivalent to GL_TEXTURE_BINDING_CUBE_MAP_ARRAY
+ \value BindingTarget2DMultisample Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE
+ \value BindingTarget2DMultisampleArray Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
+ \value BindingTargetRectangle Equivalent to GL_TEXTURE_BINDING_RECTANGLE
+ \value BindingTargetBuffer Equivalent to GL_TEXTURE_BINDING_BUFFER
+*/
+
+/*!
+ \enum QOpenGLTexture::MipMapGeneration
+ This enum defines the options to control mipmap generation.
+
+ \value GenerateMipMaps Mipmaps should be generated
+ \value DontGenerateMipMaps Mipmaps should not be generated
+*/
+
+/*!
+ \enum QOpenGLTexture::TextureUnitReset
+ This enum defines options ot control texture unit activation.
+
+ \value ResetTextureUnit The previous active texture unit will be reset
+ \value DontResetTextureUnit The previous active texture unit will not be rest
+*/
+
+/*!
+ \enum QOpenGLTexture::TextureFormat
+ This enum defines the possible texture formats. Depending upon your OpenGL
+ implementation only a subset of these may be supported.
+
+ \value NoFormat Equivalent to GL_NONE
+
+ \value R8_UNorm Equivalent to GL_R8
+ \value RG8_UNorm Equivalent to GL_RG8
+ \value RGB8_UNorm Equivalent to GL_RGB8
+ \value RGBA8_UNorm Equivalent to GL_RGBA8
+
+ \value R16_UNorm Equivalent to GL_R16
+ \value RG16_UNorm Equivalent to GL_RG16
+ \value RGB16_UNorm Equivalent to GL_RGB16
+ \value RGBA16_UNorm Equivalent to GL_RGBA16
+
+ \value R8_SNorm Equivalent to GL_R8_SNORM
+ \value RG8_SNorm Equivalent to GL_RG8_SNORM
+ \value RGB8_SNorm Equivalent to GL_RGB8_SNORM
+ \value RGBA8_SNorm Equivalent to GL_RGBA8_SNORM
+
+ \value R16_SNorm Equivalent to GL_R16_SNORM
+ \value RG16_SNorm Equivalent to GL_RG16_SNORM
+ \value RGB16_SNorm Equivalent to GL_RGB16_SNORM
+ \value RGBA16_SNorm Equivalent to GL_RGBA16_SNORM
+
+ \value R8U Equivalent to GL_R8UI
+ \value RG8U Equivalent to GL_RG8UI
+ \value RGB8U Equivalent to GL_RGB8UI
+ \value RGBA8U Equivalent to GL_RGBA8UI
+
+ \value R16U Equivalent to GL_R16UI
+ \value RG16U Equivalent to GL_RG16UI
+ \value RGB16U Equivalent to GL_RGB16UI
+ \value RGBA16U Equivalent to GL_RGBA16UI
+
+ \value R32U Equivalent to GL_R32UI
+ \value RG32U Equivalent to GL_RG32UI
+ \value RGB32U Equivalent to GL_RGB32UI
+ \value RGBA32U Equivalent to GL_RGBA32UI
+
+ \value R8I Equivalent to GL_R8I
+ \value RG8I Equivalent to GL_RG8I
+ \value RGB8I Equivalent to GL_RGB8I
+ \value RGBA8I Equivalent to GL_RGBA8I
+
+ \value R16I Equivalent to GL_R16I
+ \value RG16I Equivalent to GL_RG16I
+ \value RGB16I Equivalent to GL_RGB16I
+ \value RGBA16I Equivalent to GL_RGBA16I
+
+ \value R32I Equivalent to GL_R32I
+ \value RG32I Equivalent to GL_RG32I
+ \value RGB32I Equivalent to GL_RGB32I
+ \value RGBA32I Equivalent to GL_RGBA32I
+
+ \value R16F Equivalent to GL_R16F
+ \value RG16F Equivalent to GL_RG16F
+ \value RGB16F Equivalent to GL_RGB16F
+ \value RGBA16F Equivalent to GL_RGBA16F
+
+ \value R32F Equivalent to GL_R32F
+ \value RG32F Equivalent to GL_RG32F
+ \value RGB32F Equivalent to GL_RGB32F
+ \value RGBA32F Equivalent to GL_RGBA32F
+
+ \value RGB9E5 Equivalent to GL_RGB9_E5
+ \value RG11B10F Equivalent to GL_R11F_G11F_B10F
+ \value RG3B2 Equivalent to GL_R3_G3_B2
+ \value R5G6B5 Equivalent to GL_RGB565
+ \value RGB5A1 Equivalent to GL_RGB5_A1
+ \value RGBA4 Equivalent to GL_RGBA4
+ \value RGB10A2 Equivalent to GL_RGB10_A2UI
+
+ \value D16 Equivalent to GL_DEPTH_COMPONENT16
+ \value D24 Equivalent to GL_DEPTH_COMPONENT24
+ \value D24S8 Equivalent to GL_DEPTH24_STENCIL8
+ \value D32 Equivalent to GL_DEPTH_COMPONENT32
+ \value D32F Equivalent to GL_DEPTH_COMPONENT32F
+ \value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8
+ \value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4
+
+ \value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+ \value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ \value RGBA_DXT3 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
+ \value RGBA_DXT5 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+ \value R_ATI1N_UNorm Equivalent to GL_COMPRESSED_RED_RGTC1
+ \value R_ATI1N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RED_RGTC1
+ \value RG_ATI2N_UNorm Equivalent to GL_COMPRESSED_RG_RGTC2
+ \value RG_ATI2N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG_RGTC2
+ \value RGB_BP_UNSIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
+ \value RGB_BP_SIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
+ \value RGB_BP_UNorm Equivalent to GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
+ \value R11_EAC_UNorm Equivalent to GL_COMPRESSED_R11_EAC
+ \value R11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_R11_EAC
+ \value RG11_EAC_UNorm Equivalent to GL_COMPRESSED_RG11_EAC
+ \value RG11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG11_EAC
+ \value RGB8_ETC2 Equivalent to GL_COMPRESSED_RGB8_ETC2
+ \value SRGB8_ETC2 Equivalent to GL_COMPRESSED_SRGB8_ETC2
+ \value RGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ \value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ \value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC
+ \value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ \value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES
+ \value RGBA_ASTC_4x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_4x4_KHR
+ \value RGBA_ASTC_5x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x4_KHR
+ \value RGBA_ASTC_5x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x5_KHR
+ \value RGBA_ASTC_6x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x5_KHR
+ \value RGBA_ASTC_6x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x6_KHR
+ \value RGBA_ASTC_8x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x5_KHR
+ \value RGBA_ASTC_8x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x6_KHR
+ \value RGBA_ASTC_8x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x8_KHR
+ \value RGBA_ASTC_10x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x5_KHR
+ \value RGBA_ASTC_10x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x6_KHR
+ \value RGBA_ASTC_10x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x8_KHR
+ \value RGBA_ASTC_10x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x10_KHR
+ \value RGBA_ASTC_12x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x10_KHR
+ \value RGBA_ASTC_12x12 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x12_KHR
+ \value SRGB8_Alpha8_ASTC_4x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
+ \value SRGB8_Alpha8_ASTC_5x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
+ \value SRGB8_Alpha8_ASTC_5x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
+ \value SRGB8_Alpha8_ASTC_6x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
+ \value SRGB8_Alpha8_ASTC_6x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
+ \value SRGB8_Alpha8_ASTC_8x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
+ \value SRGB8_Alpha8_ASTC_8x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
+ \value SRGB8_Alpha8_ASTC_8x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
+ \value SRGB8_Alpha8_ASTC_10x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
+ \value SRGB8_Alpha8_ASTC_10x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
+ \value SRGB8_Alpha8_ASTC_10x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
+ \value SRGB8_Alpha8_ASTC_10x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
+ \value SRGB8_Alpha8_ASTC_12x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
+ \value SRGB8_Alpha8_ASTC_12x12 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
+
+ \value SRGB8 Equivalent to GL_SRGB8
+ \value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8
+ \value SRGB_DXT1 Equivalent to GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
+ \value SRGB_Alpha_DXT1 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
+ \value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
+ \value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+ \value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
+
+ \value DepthFormat Equivalent to GL_DEPTH_COMPONENT (only OpenGL ES 3 or ES 2 with OES_depth_texture)
+ \value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only)
+ \value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only)
+ \value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only)
+ \value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
+ \value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
+*/
+
+/*!
+ \enum QOpenGLTexture::CubeMapFace
+ This enum defines the possible CubeMap faces.
+
+ \value CubeMapPositiveX Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ \value CubeMapNegativeX Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_X
+ \value CubeMapPositiveY Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
+ \value CubeMapNegativeY Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
+ \value CubeMapPositiveZ Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Z
+ \value CubeMapNegativeZ Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+*/
+
+/*!
+ \enum QOpenGLTexture::PixelFormat
+ This enum defines the possible client-side pixel formats for a pixel
+ transfer operation.
+
+ \value NoSourceFormat Equivalent to GL_NONE
+ \value Red Equivalent to GL_RED
+ \value RG Equivalent to GL_RG
+ \value RGB Equivalent to GL_RGB
+ \value BGR Equivalent to GL_BGR
+ \value RGBA Equivalent to GL_RGBA
+ \value BGRA Equivalent to GL_BGRA
+ \value Red_Integer Equivalent to GL_RED_INTEGER
+ \value RG_Integer Equivalent to GL_RG_INTEGER
+ \value RGB_Integer Equivalent to GL_RGB_INTEGER
+ \value BGR_Integer Equivalent to GL_BGR_INTEGER
+ \value RGBA_Integer Equivalent to GL_RGBA_INTEGER
+ \value BGRA_Integer Equivalent to GL_BGRA_INTEGER
+ \value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4
+ \value Depth Equivalent to GL_DEPTH_COMPONENT
+ \value DepthStencil Equivalent to GL_DEPTH_STENCIL
+ \value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only)
+ \value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
+ \value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
+
+*/
+
+/*!
+ \enum QOpenGLTexture::PixelType
+ This enum defines the possible pixel data types for a pixel transfer operation
+
+ \value NoPixelType Equivalent to GL_NONE
+ \value Int8 Equivalent to GL_BYTE
+ \value UInt8 Equivalent to GL_UNSIGNED_BYTE
+ \value Int16 Equivalent to GL_SHORT
+ \value UInt16 Equivalent to GL_UNSIGNED_SHORT
+ \value Int32 Equivalent to GL_INT
+ \value UInt32 Equivalent to GL_UNSIGNED_INT
+ \value Float16 Equivalent to GL_HALF_FLOAT
+ \value Float16OES Equivalent to GL_HALF_FLOAT_OES
+ \value Float32 Equivalent to GL_FLOAT
+ \value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV
+ \value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV
+ \value UInt8_RG3B2 Equivalent to GL_UNSIGNED_BYTE_3_3_2
+ \value UInt8_RG3B2_Rev Equivalent to GL_UNSIGNED_BYTE_2_3_3_REV
+ \value UInt16_RGB5A1 Equivalent to GL_UNSIGNED_SHORT_5_5_5_1
+ \value UInt16_RGB5A1_Rev Equivalent to GL_UNSIGNED_SHORT_1_5_5_5_REV
+ \value UInt16_R5G6B5 Equivalent to GL_UNSIGNED_SHORT_5_6_5
+ \value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV
+ \value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4
+ \value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV
+ \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8
+ \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV
+ \value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2
+ \value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV
+ \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4
+ \value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4
+*/
+
+/*!
+ \enum QOpenGLTexture::Feature
+ This enum defines the OpenGL texture-related features that can be tested for.
+
+ \value ImmutableStorage Support for immutable texture storage
+ \value ImmutableMultisampleStorage Support for immutable texture storage with
+ multisample targets
+ \value TextureRectangle Support for the GL_TEXTURE_RECTANGLE target
+ \value TextureArrays Support for texture targets with array layers
+ \value Texture3D Support for the 3 dimensional texture target
+ \value TextureMultisample Support for texture targets that have multisample capabilities
+ \value TextureBuffer Support for textures that use OpenGL buffer objects
+ as their data source
+ \value TextureCubeMapArrays Support for cubemap array texture target
+ \value Swizzle Support for texture component swizzle masks
+ \value StencilTexturing Support for stencil texturing (i.e. looking up depth or stencil
+ components of a combined depth/stencil format texture in GLSL shaders).
+ \value AnisotropicFiltering Support for anisotropic texture filtering
+ \value NPOTTextures Basic support for non-power-of-two textures
+ \value NPOTTextureRepeat Full support for non-power-of-two textures including texture
+ repeat modes
+ \value Texture1D Support for the 1 dimensional texture target
+ \value TextureComparisonOperators Support for texture comparison operators
+ \value TextureMipMapLevel Support for setting the base and maximum mipmap levels
+*/
+
+/*!
+ \enum QOpenGLTexture::SwizzleComponent
+ This enum defines the texture color components that can be assigned a swizzle mask.
+
+ \value SwizzleRed The red component. Equivalent to GL_TEXTURE_SWIZZLE_R
+ \value SwizzleGreen The green component. Equivalent to GL_TEXTURE_SWIZZLE_G
+ \value SwizzleBlue The blue component. Equivalent to GL_TEXTURE_SWIZZLE_B
+ \value SwizzleAlpha The alpha component. Equivalent to GL_TEXTURE_SWIZZLE_A
+*/
+
+/*!
+ \enum QOpenGLTexture::SwizzleValue
+ This enum defines the possible mask values for texture swizzling.
+
+ \value RedValue Maps the component to the red channel. Equivalent to GL_RED
+ \value GreenValue Maps the component to the green channel. Equivalent to GL_GREEN
+ \value BlueValue Maps the component to the blue channel. Equivalent to GL_BLUE
+ \value AlphaValue Maps the component to the alpha channel. Equivalent to GL_ALPHA
+ \value ZeroValue Maps the component to a fixed value of 0. Equivalent to GL_ZERO
+ \value OneValue Maps the component to a fixed value of 1. Equivalent to GL_ONE
+*/
+
+/*!
+ \enum QOpenGLTexture::WrapMode
+ This enum defines the possible texture coordinate wrapping modes.
+
+ \value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT
+ \value MirroredRepeat Texture coordinate is reflected about 0 and 1. Equivalent to GL_MIRRORED_REPEAT
+ \value ClampToEdge Clamps the texture coordinates to [0,1]. Equivalent to GL_CLAMP_TO_EDGE
+ \value ClampToBorder As for ClampToEdge but also blends samples at 0 and 1 with a
+ fixed border color. Equivalent to GL_CLAMP_TO_BORDER
+*/
+
+/*!
+ \enum QOpenGLTexture::CoordinateDirection
+ This enum defines the possible texture coordinate directions
+
+ \value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S
+ \value DirectionT The vertical direction. Equivalent to GL_TEXTURE_WRAP_T
+ \value DirectionR The depth direction. Equivalent to GL_TEXTURE_WRAP_R
+*/
+
+/*!
+ Creates a QOpenGLTexture object that can later be bound to \a target.
+
+ This does not create the underlying OpenGL texture object. Therefore,
+ construction using this constructor does not require a valid current
+ OpenGL context.
+*/
+QOpenGLTexture::QOpenGLTexture(Target target)
+ : d_ptr(new QOpenGLTexturePrivate(target, this))
+{
+}
+
+/*!
+ Creates a QOpenGLTexture object that can later be bound to the 2D texture
+ target and contains the pixel data contained in \a image. If you wish
+ to have a chain of mipmaps generated then set \a genMipMaps to \c true (this
+ is the default).
+
+ This does create the underlying OpenGL texture object. Therefore,
+ construction using this constructor does require a valid current
+ OpenGL context.
+*/
+QOpenGLTexture::QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps)
+ : QOpenGLTexture(QOpenGLTexture::Target2D)
+{
+ setData(image, genMipMaps);
+}
+
+QOpenGLTexture::~QOpenGLTexture()
+{
+}
+
+/*!
+ Returns the binding target of this texture.
+
+ \since 5.4
+*/
+QOpenGLTexture::Target QOpenGLTexture::target() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->target;
+}
+
+/*!
+ Creates the underlying OpenGL texture object. This requires a current valid
+ OpenGL context. If the texture object already exists, this function does
+ nothing.
+
+ Once the texture object is created you can obtain the object
+ name from the textureId() function. This may be useful if you wish to make
+ some raw OpenGL calls related to this texture.
+
+ Normally it should not be necessary to call this function directly as all
+ functions that set properties of the texture object implicitly call create()
+ on your behalf.
+
+ Returns \c true if the creation succeeded, otherwise returns \c false.
+
+ \sa destroy(), isCreated(), textureId()
+*/
+bool QOpenGLTexture::create()
+{
+ Q_D(QOpenGLTexture);
+ return d->create();
+}
+
+/*!
+ Destroys the underlying OpenGL texture object. This requires a current valid
+ OpenGL context.
+
+ \sa create(), isCreated(), textureId()
+*/
+void QOpenGLTexture::destroy()
+{
+ Q_D(QOpenGLTexture);
+ return d->destroy();
+}
+
+/*!
+ Returns \c true if the underlying OpenGL texture object has been created.
+
+ \sa create(), destroy(), textureId()
+*/
+bool QOpenGLTexture::isCreated() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->textureId != 0;
+}
+
+/*!
+ Returns the name of the underlying OpenGL texture object or 0 if it has
+ not yet been created.
+
+ \sa create(), destroy(), isCreated()
+*/
+GLuint QOpenGLTexture::textureId() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->textureId;
+}
+
+/*!
+ Binds this texture to the currently active texture unit ready for
+ rendering. Note that you do not need to bind QOpenGLTexture objects
+ in order to modify them as the implementation makes use of the
+ EXT_direct_state_access extension where available and simulates it
+ where it is not.
+
+ \sa release()
+*/
+void QOpenGLTexture::bind()
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->bind();
+}
+
+/*!
+ Binds this texture to texture unit \a unit ready for
+ rendering. Note that you do not need to bind QOpenGLTexture objects
+ in order to modify them as the implementation makes use of the
+ EXT_direct_state_access extension where available and simulates it
+ where it is not.
+
+ If parameter \a reset is \c true then this function will restore
+ the active unit to the texture unit that was active upon entry.
+
+ \sa release()
+*/
+void QOpenGLTexture::bind(uint unit, TextureUnitReset reset)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->bind(unit, reset);
+}
+
+/*!
+ Unbinds this texture from the currently active texture unit.
+
+ \sa bind()
+*/
+void QOpenGLTexture::release()
+{
+ Q_D(QOpenGLTexture);
+ d->release();
+}
+
+/*!
+ Unbinds this texture from texture unit \a unit.
+
+ If parameter \a reset is \c true then this function
+ will restore the active unit to the texture unit that was active
+ upon entry.
+*/
+void QOpenGLTexture::release(uint unit, TextureUnitReset reset)
+{
+ Q_D(QOpenGLTexture);
+ d->release(unit, reset);
+}
+
+/*!
+ Returns \c true if this texture is bound to the corresponding target
+ of the currently active texture unit.
+
+ \sa bind(), release()
+*/
+bool QOpenGLTexture::isBound() const
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ return d->isBound();
+}
+
+/*!
+ Returns \c true if this texture is bound to the corresponding target
+ of texture unit \a unit.
+
+ \sa bind(), release()
+*/
+bool QOpenGLTexture::isBound(uint unit)
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ return d->isBound(unit);
+}
+
+/*!
+ Returns the textureId of the texture that is bound to the \a target
+ of the currently active texture unit.
+*/
+GLuint QOpenGLTexture::boundTextureId(BindingTarget target)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
+ return 0;
+ }
+
+ GLint textureId = 0;
+ ctx->functions()->glGetIntegerv(target, &textureId);
+ return static_cast<GLuint>(textureId);
+}
+
+/*!
+ Returns the textureId of the texture that is bound to the \a target
+ of the texture unit \a unit.
+*/
+GLuint QOpenGLTexture::boundTextureId(uint unit, BindingTarget target)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
+ return 0;
+ }
+
+ QOpenGLFunctions *funcs = ctx->functions();
+ funcs->initializeOpenGLFunctions();
+
+ GLint oldTextureUnit = 0;
+ funcs->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
+
+ funcs->glActiveTexture(unit);
+ GLint textureId = 0;
+ funcs->glGetIntegerv(target, &textureId);
+ funcs->glActiveTexture(oldTextureUnit);
+
+ return static_cast<GLuint>(textureId);
+}
+
+/*!
+ Sets the format of this texture object to \a format. This function
+ must be called before texture storage is allocated.
+
+ Note that all formats may not be supported. The exact set of supported
+ formats is dependent upon your OpenGL implementation and version.
+
+ \sa format(), allocateStorage()
+*/
+void QOpenGLTexture::setFormat(TextureFormat format)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("QOpenGLTexture::setFormat(): Cannot change format once storage has been allocated");
+ return;
+ }
+
+ d->format = format;
+
+ switch (format) {
+ case NoFormat:
+ d->formatClass = NoFormatClass;
+ break;
+
+ case RGBA32F:
+ case RGBA32U:
+ case RGBA32I:
+ d->formatClass = FormatClass_128Bit;
+ break;
+
+ case RGB32F:
+ case RGB32U:
+ case RGB32I:
+ d->formatClass = FormatClass_96Bit;
+ break;
+
+ case RGBA16F:
+ case RG32F:
+ case RGBA16U:
+ case RG32U:
+ case RGBA16I:
+ case RG32I:
+ case RGBA16_UNorm:
+ case RGBA16_SNorm:
+ d->formatClass = FormatClass_64Bit;
+ break;
+
+ case RGB16_UNorm:
+ case RGB16_SNorm:
+ case RGB16F:
+ case RGB16U:
+ case RGB16I:
+ d->formatClass = FormatClass_48Bit;
+ break;
+
+ case RG16F:
+ case RG11B10F:
+ case R32F:
+ case RGB10A2:
+ case RGBA8U:
+ case RG16U:
+ case R32U:
+ case RGBA8I:
+ case RG16I:
+ case R32I:
+ case RGBA8_UNorm:
+ case RG16_UNorm:
+ case RGBA8_SNorm:
+ case RG16_SNorm:
+ case SRGB8_Alpha8:
+ case RGB9E5:
+ d->formatClass = FormatClass_32Bit;
+ break;
+
+ case RGB8_UNorm:
+ case RGB8_SNorm:
+ case SRGB8:
+ case RGB8U:
+ case RGB8I:
+ d->formatClass = FormatClass_24Bit;
+ break;
+
+ case R16F:
+ case RG8U:
+ case R16U:
+ case RG8I:
+ case R16I:
+ case RG8_UNorm:
+ case R16_UNorm:
+ case RG8_SNorm:
+ case R16_SNorm:
+ d->formatClass = FormatClass_16Bit;
+ break;
+
+ case R8U:
+ case R8I:
+ case R8_UNorm:
+ case R8_SNorm:
+ d->formatClass = FormatClass_8Bit;
+ break;
+
+ case R_ATI1N_UNorm:
+ case R_ATI1N_SNorm:
+ d->formatClass = FormatClass_RGTC1_R;
+ break;
+
+ case RG_ATI2N_UNorm:
+ case RG_ATI2N_SNorm:
+ d->formatClass = FormatClass_RGTC2_RG;
+ break;
+
+ case RGB_BP_UNorm:
+ case SRGB_BP_UNorm:
+ d->formatClass = FormatClass_BPTC_Unorm;
+ break;
+
+ case RGB_BP_UNSIGNED_FLOAT:
+ case RGB_BP_SIGNED_FLOAT:
+ d->formatClass = FormatClass_BPTC_Float;
+ break;
+
+ case RGB_DXT1:
+ case SRGB_DXT1:
+ d->formatClass = FormatClass_S3TC_DXT1_RGB;
+ break;
+
+ case RGBA_DXT1:
+ case SRGB_Alpha_DXT1:
+ d->formatClass = FormatClass_S3TC_DXT1_RGBA;
+ break;
+
+ case RGBA_DXT3:
+ case SRGB_Alpha_DXT3:
+ d->formatClass = FormatClass_S3TC_DXT3_RGBA;
+ break;
+
+ case RGBA_DXT5:
+ case SRGB_Alpha_DXT5:
+ d->formatClass = FormatClass_S3TC_DXT5_RGBA;
+ break;
+
+ case QOpenGLTexture::R11_EAC_UNorm:
+ case QOpenGLTexture::R11_EAC_SNorm:
+ case QOpenGLTexture::RG11_EAC_UNorm:
+ case QOpenGLTexture::RG11_EAC_SNorm:
+ case QOpenGLTexture::RGB8_ETC2:
+ case QOpenGLTexture::SRGB8_ETC2:
+ case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
+ case QOpenGLTexture::RGBA8_ETC2_EAC:
+ case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
+ case QOpenGLTexture::RGB8_ETC1:
+ case RG3B2:
+ case R5G6B5:
+ case RGB5A1:
+ case RGBA4:
+ case D16:
+ case D24:
+ case D24S8:
+ case D32:
+ case D32F:
+ case D32FS8X24:
+ case S8:
+ case DepthFormat:
+ case AlphaFormat:
+ case RGBFormat:
+ case RGBAFormat:
+ case LuminanceFormat:
+ case LuminanceAlphaFormat:
+ case QOpenGLTexture::RGBA_ASTC_4x4:
+ case QOpenGLTexture::RGBA_ASTC_5x4:
+ case QOpenGLTexture::RGBA_ASTC_5x5:
+ case QOpenGLTexture::RGBA_ASTC_6x5:
+ case QOpenGLTexture::RGBA_ASTC_6x6:
+ case QOpenGLTexture::RGBA_ASTC_8x5:
+ case QOpenGLTexture::RGBA_ASTC_8x6:
+ case QOpenGLTexture::RGBA_ASTC_8x8:
+ case QOpenGLTexture::RGBA_ASTC_10x5:
+ case QOpenGLTexture::RGBA_ASTC_10x6:
+ case QOpenGLTexture::RGBA_ASTC_10x8:
+ case QOpenGLTexture::RGBA_ASTC_10x10:
+ case QOpenGLTexture::RGBA_ASTC_12x10:
+ case QOpenGLTexture::RGBA_ASTC_12x12:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
+ case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
+ d->formatClass = FormatClass_Unique;
+ break;
+ }
+}
+
+/*!
+ Returns the format of this texture object.
+
+ \sa setFormat()
+*/
+QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->format;
+}
+
+static bool isNpot(int width, int height = 1, int depth = 1)
+{
+ return width & (width-1) || height & (height-1) || depth & (depth-1);
+}
+
+/*!
+ Sets the dimensions of this texture object to \a width,
+ \a height, and \a depth. The default for each dimension is 1.
+ The maximum allowable texture size is dependent upon your OpenGL
+ implementation. Allocating storage for a texture less than the
+ maximum size can still fail if your system is low on resources.
+
+ If a non-power-of-two \a width, \a height or \a depth is provided and your
+ OpenGL implementation doesn't have support for repeating non-power-of-two
+ textures, then the wrap mode is automatically set to ClampToEdge.
+
+ \sa width(), height(), depth()
+*/
+void QOpenGLTexture::setSize(int width, int height, int depth)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot resize a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setSize()");
+ return;
+ }
+
+ if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
+ d->setWrapMode(WrapMode::ClampToEdge);
+
+ switch (d->target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::TargetBuffer:
+ d->dimensions[0] = width;
+ Q_UNUSED(height);
+ Q_UNUSED(depth);
+ break;
+
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->dimensions[0] = width;
+ d->dimensions[1] = height;
+ Q_UNUSED(depth);
+ break;
+
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ if (width != height)
+ qWarning("QAbstractOpenGLTexture::setSize(): Cube map textures must be square");
+ d->dimensions[0] = d->dimensions[1] = width;
+ Q_UNUSED(depth);
+ break;
+
+ case QOpenGLTexture::Target3D:
+ d->dimensions[0] = width;
+ d->dimensions[1] = height;
+ d->dimensions[2] = depth;
+ break;
+ }
+}
+
+/*!
+ Returns the width of a 1D, 2D or 3D texture.
+
+ \sa height(), depth(), setSize()
+*/
+int QOpenGLTexture::width() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->dimensions[0];
+}
+
+/*!
+ Returns the height of a 2D or 3D texture.
+
+ \sa width(), depth(), setSize()
+*/
+int QOpenGLTexture::height() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->dimensions[1];
+}
+
+/*!
+ Returns the depth of a 3D texture.
+
+ \sa width(), height(), setSize()
+*/
+int QOpenGLTexture::depth() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->dimensions[2];
+}
+
+/*!
+ For texture targets that support mipmaps, this function
+ sets the requested number of mipmap \a levels to allocate storage
+ for. This function should be called before storage is allocated
+ for the texture.
+
+ If the texture target does not support mipmaps this function
+ has no effect.
+
+ \sa mipLevels(), maximumMipLevels(), isStorageAllocated()
+*/
+void QOpenGLTexture::setMipLevels(int levels)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set mip levels on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setMipLevels()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::Target3D:
+ d->requestedMipLevels = levels;
+ break;
+
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ qWarning("QAbstractOpenGLTexture::setMipLevels(): This texture target does not support mipmaps");
+ break;
+ }
+}
+
+/*!
+ Returns the number of mipmap levels for this texture. If storage
+ has not yet been allocated for this texture it returns the
+ requested number of mipmap levels.
+
+ \sa setMipLevels(), maximumMipLevels(), isStorageAllocated()
+*/
+int QOpenGLTexture::mipLevels() const
+{
+ Q_D(const QOpenGLTexture);
+ return isStorageAllocated() ? d->mipLevels : d->requestedMipLevels;
+}
+
+/*!
+ Returns the maximum number of mipmap levels that this texture
+ can have given the current dimensions.
+
+ \sa setMipLevels(), mipLevels(), setSize()
+*/
+int QOpenGLTexture::maximumMipLevels() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->maximumMipLevelCount();
+}
+
+/*!
+ Sets the number of array \a layers to allocate storage for. This
+ function should be called before storage is allocated for the texture.
+
+ For targets that do not support array layers this function has
+ no effect.
+
+ \sa layers(), isStorageAllocated()
+*/
+void QOpenGLTexture::setLayers(int layers)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set layers on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setLayers()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->layers = layers;
+ break;
+
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+ case QOpenGLTexture::Target2DMultisample:
+ qWarning("Texture target does not support array layers");
+ break;
+ }
+}
+
+/*!
+ Returns the number of array layers for this texture. If
+ storage has not yet been allocated for this texture then
+ this function returns the requested number of array layers.
+
+ For texture targets that do not support array layers this
+ will return 1.
+
+ \sa setLayers(), isStorageAllocated()
+*/
+int QOpenGLTexture::layers() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->layers;
+}
+
+/*!
+ Returns the number of faces for this texture. For cubemap
+ and cubemap array type targets this will be 6.
+
+ For non-cubemap type targets this will return 1.
+*/
+int QOpenGLTexture::faces() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->faces;
+}
+
+/*!
+ Sets the number of \a samples to allocate storage for when rendering to
+ a multisample capable texture target. This function should
+ be called before storage is allocated for the texture.
+
+ For targets that do not support multisampling this function has
+ no effect.
+
+ \sa samples(), isStorageAllocated()
+*/
+void QOpenGLTexture::setSamples(int samples)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set sample count on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setSamples()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->samples = samples;
+ break;
+
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+
+ qWarning("Texture target does not support multisampling");
+ break;
+ }
+}
+
+/*!
+ Returns the number of multisample sample points for this texture.
+ If storage has not yet been allocated for this texture then
+ this function returns the requested number of samples.
+
+ For texture targets that do not support multisampling this
+ will return 0.
+
+ \sa setSamples(), isStorageAllocated()
+*/
+int QOpenGLTexture::samples() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->samples;
+}
+
+/*!
+ Sets whether the sample positions and number of samples used with
+ a multisample capable texture target to \a fixed. If set to \c true
+ the sample positions and number of samples used are the same for
+ all texels in the image and will not depend upon the image size or
+ internal format. This function should be called before storage is allocated
+ for the texture.
+
+ For targets that do not support multisampling this function has
+ no effect.
+
+ The default value is \c true.
+
+ \sa isFixedSamplePositions(), isStorageAllocated()
+*/
+void QOpenGLTexture::setFixedSamplePositions(bool fixed)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (isStorageAllocated()) {
+ qWarning("Cannot set sample positions on a texture that already has storage allocated.\n"
+ "To do so, destroy() the texture and then create() and setFixedSamplePositions()");
+ return;
+ }
+
+ switch (d->target) {
+ case QOpenGLTexture::Target2DMultisample:
+ case QOpenGLTexture::Target2DMultisampleArray:
+ d->fixedSamplePositions = fixed;
+ break;
+
+ case QOpenGLTexture::Target1D:
+ case QOpenGLTexture::Target2D:
+ case QOpenGLTexture::Target3D:
+ case QOpenGLTexture::Target1DArray:
+ case QOpenGLTexture::Target2DArray:
+ case QOpenGLTexture::TargetCubeMap:
+ case QOpenGLTexture::TargetCubeMapArray:
+ case QOpenGLTexture::TargetBuffer:
+ case QOpenGLTexture::TargetRectangle:
+
+ qWarning("Texture target does not support multisampling");
+ break;
+ }
+}
+
+/*!
+ Returns whether this texture uses a fixed pattern of multisample
+ samples. If storage has not yet been allocated for this texture then
+ this function returns the requested fixed sample position setting.
+
+ For texture targets that do not support multisampling this
+ will return \c true.
+
+ \sa setFixedSamplePositions(), isStorageAllocated()
+*/
+bool QOpenGLTexture::isFixedSamplePositions() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->fixedSamplePositions;
+}
+
+/*!
+ Allocates server-side storage for this texture object taking
+ into account, the format, dimensions, mipmap levels, array
+ layers and cubemap faces.
+
+ Once storage has been allocated it is no longer possible to change
+ these properties.
+
+ If supported QOpenGLTexture makes use of immutable texture
+ storage.
+
+ Once storage has been allocated for the texture then pixel data
+ can be uploaded via one of the setData() overloads.
+
+ \note If immutable texture storage is not available,
+ then a default pixel format and pixel type will be used to
+ create the mutable storage. You can use the other
+ allocateStorage() overload to specify exactly the pixel format
+ and the pixel type to use when allocating mutable storage;
+ this is particulary useful under certain OpenGL ES implementations
+ (notably, OpenGL ES 2), where the pixel format and the pixel type
+ used at allocation time must perfectly match the format
+ and the type passed to any subsequent setData() call.
+
+ \sa isStorageAllocated(), setData()
+*/
+void QOpenGLTexture::allocateStorage()
+{
+ Q_D(QOpenGLTexture);
+ if (d->create()) {
+ const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(d->format);
+ const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(d->format);
+ d->allocateStorage(pixelFormat, pixelType);
+ }
+}
+
+/*!
+ \since 5.5
+
+ Allocates server-side storage for this texture object taking
+ into account, the format, dimensions, mipmap levels, array
+ layers and cubemap faces.
+
+ Once storage has been allocated it is no longer possible to change
+ these properties.
+
+ If supported QOpenGLTexture makes use of immutable texture
+ storage. However, if immutable texture storage is not available,
+ then the specified \a pixelFormat and \a pixelType will be used
+ to allocate mutable storage; note that in certain OpenGL implementations
+ (notably, OpenGL ES 2) they must perfectly match the format
+ and the type passed to any subsequent setData() call.
+
+ Once storage has been allocated for the texture then pixel data
+ can be uploaded via one of the setData() overloads.
+
+ \sa isStorageAllocated(), setData()
+*/
+void QOpenGLTexture::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
+{
+ Q_D(QOpenGLTexture);
+ if (d->create())
+ d->allocateStorage(pixelFormat, pixelType);
+}
+
+/*!
+ Returns \c true if server-side storage for this texture as been
+ allocated.
+
+ The texture format, dimensions, mipmap levels and array layers
+ cannot be altered once storage ihas been allocated.
+
+ \sa allocateStorage(), setSize(), setMipLevels(), setLayers(), setFormat()
+*/
+bool QOpenGLTexture::isStorageAllocated() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->storageAllocated;
+}
+
+/*!
+ Attempts to create a texture view onto this texture. A texture
+ view is somewhat analogous to a view in SQL in that it presents
+ a restricted or reinterpreted view of the original data. Texture
+ views do not allocate any more server-side storage, insted relying
+ on the storage buffer of the source texture.
+
+ Texture views are only available when using immutable storage. For
+ more information on texture views see
+ http://www.opengl.org/wiki/Texture_Storage#Texture_views.
+
+ The \a target argument specifies the target to use for the view.
+ Only some targets can be used depending upon the target of the original
+ target. For e.g. a view onto a Target1DArray texture can specify
+ either Target1DArray or Target1D but for the latter the number of
+ array layers specified with \a minimumLayer and \a maximumLayer must
+ be exactly 1.
+
+ Simpliar constraints apply for the \a viewFormat. See the above link
+ and the specification for more details.
+
+ The \a minimumMipmapLevel, \a maximumMipmapLevel, \a minimumLayer,
+ and \a maximumLayer arguments serve to restrict the parts of the
+ texture accessible by the texture view.
+
+ If creation of the texture view fails this function will return
+ 0. If the function succeeds it will return a pointer to a new
+ QOpenGLTexture object that will return \c true from its isTextureView()
+ function.
+
+ \sa isTextureView()
+*/
+QOpenGLTexture *QOpenGLTexture::createTextureView(Target target,
+ TextureFormat viewFormat,
+ int minimumMipmapLevel, int maximumMipmapLevel,
+ int minimumLayer, int maximumLayer) const
+{
+ Q_D(const QOpenGLTexture);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set create a texture view of a texture that does not have storage allocated.");
+ return nullptr;
+ }
+ Q_ASSERT(maximumMipmapLevel >= minimumMipmapLevel);
+ Q_ASSERT(maximumLayer >= minimumLayer);
+ return d->createTextureView(target, viewFormat,
+ minimumMipmapLevel, maximumMipmapLevel,
+ minimumLayer, maximumLayer);
+}
+
+/*!
+ Returns \c true if this texture object is actually a view onto another
+ texture object.
+
+ \sa createTextureView()
+*/
+bool QOpenGLTexture::isTextureView() const
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ return d->textureView;
+}
+
+/*!
+ Uploads pixel \a data for this texture object \a mipLevel, array \a layer, and \a cubeFace.
+ Storage must have been allocated before uploading pixel data. Some overloads of setData()
+ will set appropriate dimensions, mipmap levels, and array layers and then allocate storage
+ for you if they have enough information to do so. This will be noted in the function
+ documentation.
+
+ The structure of the pixel data pointed to by \a data is specified by \a sourceFormat
+ and \a sourceType. The pixel data upload can optionally be controlled by \a options.
+
+ If using a compressed format() then you should use setCompressedData() instead of this
+ function.
+
+ \since 5.3
+ \sa setCompressedData()
+*/
+void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \since 5.9
+ \overload
+
+ Parameter \a layerCount is the number of layers in a texture array
+ that are being uploaded/populated by this call.
+*/
+void QOpenGLTexture::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setData(mipLevel, layer, layerCount, cubeFace, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \since 5.3
+ \overload
+*/
+void QOpenGLTexture::setData(int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \since 5.3
+ \overload
+*/
+void QOpenGLTexture::setData(int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \since 5.3
+ \overload
+*/
+void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ 0, 0, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image. The mip map level the sub image we want to
+ update is specified with \a mipLevel.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, 0, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image. The mip map level and layerof the sub image we want to
+ update are specified with \a mipLevel and \a layer.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, 1,
+ QOpenGLTexture::CubeMapPositiveX, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.The mip map level, layer and cube map face of the sub
+ image we want to update are specified with \a mipLevel, \a layer and \a
+ face.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace face,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, 1,
+ face, sourceFormat,
+ sourceType, data, options);
+}
+
+/*!
+ \since 5.14
+ \overload
+
+ This overload is to be used to update a part of the texture. Parameters \a
+ xOffset, \a yOffset, \a zOffset specify the texel offsets within the
+ texture. Parameters \a width, \a height and \a depth specify the dimensions
+ of the sub image.The mip map level, starting layer, cube map face and
+ number of layers of the sub image we want to update are specified with \a
+ mipLevel, \a layer, \a face and \a layerCount.
+
+ The structure of the pixel data pointed to by \a data is specified by \a
+ sourceFormat and \a sourceType. The pixel data upload can optionally be
+ controlled by \a options.
+*/
+void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace face, int layerCount,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(xOffset, yOffset, zOffset,
+ width, height, depth,
+ mipLevel, layer, layerCount,
+ face, sourceFormat,
+ sourceType, data, options);
+}
+
+#if QT_DEPRECATED_SINCE(5, 3)
+/*!
+ \obsolete
+ \overload
+
+ \sa setCompressedData()
+*/
+void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setData(int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setData(int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
+}
+#endif
+
+/*!
+ This overload of setData() will allocate storage for you.
+ The pixel data is contained in \a image. Mipmaps are generated by default.
+ Set \a genMipMaps to \l DontGenerateMipMaps to turn off mipmap generation.
+
+ \overload
+*/
+void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ if (!context) {
+ qWarning("QOpenGLTexture::setData() requires a valid current context");
+ return;
+ }
+
+ if (image.isNull()) {
+ qWarning("QOpenGLTexture::setData() tried to set a null image");
+ return;
+ }
+
+ if (context->isOpenGLES() && context->format().majorVersion() < 3)
+ setFormat(QOpenGLTexture::RGBAFormat);
+ else
+ setFormat(QOpenGLTexture::RGBA8_UNorm);
+
+ setSize(image.width(), image.height());
+ setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1);
+ allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
+
+ // Upload pixel data and generate mipmaps
+ QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions);
+}
+
+/*!
+ Uploads compressed pixel \a data to \a mipLevel, array \a layer, and \a cubeFace.
+ The pixel transfer can optionally be controlled with \a options. The \a dataSize
+ argument should specify the size of the data pointed to by \a data.
+
+ If not using a compressed format() then you should use setData() instead of this
+ function.
+
+ \since 5.3
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options);
+}
+
+/*!
+ \since 5.9
+ \overload
+
+ Parameter \a layerCount is the number of layers in a texture array
+ that are being uploaded/populated by this call.
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, int dataSize, const void *data, const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setCompressedData(mipLevel, layer, layerCount, cubeFace, dataSize, data, options);
+}
+
+/*!
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+
+/*!
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+
+/*!
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+
+#if QT_DEPRECATED_SINCE(5, 3)
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
+ int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ if (!isStorageAllocated()) {
+ qWarning("Cannot set data on a texture that does not have storage allocated.\n"
+ "To do so call allocateStorage() before this function");
+ return;
+ }
+ d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+
+/*!
+ \obsolete
+ \overload
+*/
+void QOpenGLTexture::setCompressedData(int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->textureId);
+ d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
+}
+#endif
+
+/*!
+ Returns \c true if your OpenGL implementation and version supports the texture
+ feature \a feature.
+*/
+bool QOpenGLTexture::hasFeature(Feature feature)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning("QOpenGLTexture::hasFeature() requires a valid current context");
+ return false;
+ }
+
+ QSurfaceFormat f = ctx->format();
+
+ bool supported = false;
+
+#if !defined(QT_OPENGL_ES_2)
+ if (!ctx->isOpenGLES()) {
+ switch (feature) {
+ case ImmutableMultisampleStorage:
+ supported = f.version() >= qMakePair(4, 3)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage_multisample"));
+ break;
+
+ case TextureBuffer:
+ supported = f.version() >= qMakePair(3, 0)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_buffer_object"));
+ break;
+
+ case StencilTexturing:
+ supported = f.version() >= qMakePair(4, 3)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_stencil_texturing"));
+ break;
+
+ case ImmutableStorage:
+ supported = f.version() >= qMakePair(4, 2)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage"))
+ || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage"));
+ break;
+
+ case TextureCubeMapArrays:
+ supported = f.version() >= qMakePair(4, 0)
+ || ctx->hasExtension(QByteArrayLiteral("ARB_texture_cube_map_array"));
+ break;
+
+ case Swizzle:
+ supported = f.version() >= qMakePair(3, 3)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_swizzle"));
+ break;
+
+ case TextureMultisample:
+ supported = f.version() >= qMakePair(3, 2)
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_multisample"));
+ break;
+
+ case TextureArrays:
+ supported = f.version() >= qMakePair(3, 0)
+ || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_array"));
+ break;
+
+ case TextureRectangle:
+ supported = f.version() >= qMakePair(2, 1)
+ || ctx->hasExtension(QByteArrayLiteral("ARB_texture_rectangle"));
+ break;
+
+ case Texture3D:
+ supported = f.version() >= qMakePair(1, 3);
+ break;
+
+ case AnisotropicFiltering:
+ supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
+ break;
+
+ case NPOTTextures:
+ case NPOTTextureRepeat:
+ supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
+ break;
+
+ case Texture1D:
+ supported = f.version() >= qMakePair(1, 1);
+ break;
+
+ case TextureComparisonOperators:
+ // GL 1.4 and GL_ARB_shadow alone support only LEQUAL and GEQUAL;
+ // since we're talking about history anyhow avoid to be extra pedantic
+ // in the feature set, and simply claim supported if we have the full set of operators
+ // (which has been added into 1.5 / GL_EXT_shadow_funcs).
+ supported = f.version() >= qMakePair(1, 5)
+ || (ctx->hasExtension(QByteArrayLiteral("GL_ARB_shadow"))
+ && ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_funcs")));
+ break;
+
+ case TextureMipMapLevel:
+ supported = f.version() >= qMakePair(1, 2);
+ break;
+
+ case MaxFeatureFlag:
+ break;
+ }
+ }
+
+ if (ctx->isOpenGLES())
+#endif
+ {
+ const char *renderer = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_RENDERER));
+ switch (feature) {
+ case ImmutableStorage:
+ supported = (f.version() >= qMakePair(3, 0) || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")))
+ && !(renderer && strstr(renderer, "Mali")); // do not use on Mali: QTBUG-45106
+ break;
+
+ case ImmutableMultisampleStorage:
+ supported = f.version() >= qMakePair(3, 1);
+ break;
+
+ case TextureRectangle:
+ break;
+
+ case TextureArrays:
+ supported = f.version() >= qMakePair(3, 0);
+ break;
+
+ case Texture3D:
+ supported = f.version() >= qMakePair(3, 0)
+ || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"));
+ break;
+
+ case TextureMultisample:
+ supported = f.version() >= qMakePair(3, 1);
+ break;
+
+ case TextureBuffer:
+ break;
+
+ case TextureCubeMapArrays:
+ break;
+
+ case Swizzle:
+ supported = f.version() >= qMakePair(3, 0);
+ break;
+
+ case StencilTexturing:
+ break;
+
+ case AnisotropicFiltering:
+ supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
+ break;
+
+ case NPOTTextures:
+ case NPOTTextureRepeat:
+ supported = f.version() >= qMakePair(3,0)
+ || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot"))
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
+ break;
+
+ case Texture1D:
+ break;
+
+ case TextureComparisonOperators:
+ supported = f.version() >= qMakePair(3, 0)
+ || ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_samplers"));
+ break;
+
+ case TextureMipMapLevel:
+ supported = f.version() >= qMakePair(3, 0);
+ break;
+
+ case MaxFeatureFlag:
+ break;
+ }
+ }
+
+ return supported;
+}
+
+/*!
+ Sets the base mipmap level used for all texture lookups with this texture to \a baseLevel.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa mipBaseLevel(), setMipMaxLevel(), setMipLevelRange()
+*/
+void QOpenGLTexture::setMipBaseLevel(int baseLevel)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (!d->features.testFlag(TextureMipMapLevel)) {
+ qWarning("QOpenGLTexture::setMipBaseLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
+ return;
+ }
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(baseLevel <= d->maxLevel);
+ d->baseLevel = baseLevel;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
+}
+
+/*!
+ Returns the mipmap base level used for all texture lookups with this texture.
+ The default is 0.
+
+ \sa setMipBaseLevel(), mipMaxLevel(), mipLevelRange()
+*/
+int QOpenGLTexture::mipBaseLevel() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->baseLevel;
+}
+
+/*!
+ Sets the maximum mipmap level used for all texture lookups with this texture to \a maxLevel.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa mipMaxLevel(), setMipBaseLevel(), setMipLevelRange()
+*/
+void QOpenGLTexture::setMipMaxLevel(int maxLevel)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (!d->features.testFlag(TextureMipMapLevel)) {
+ qWarning("QOpenGLTexture::setMipMaxLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
+ return;
+ }
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->baseLevel <= maxLevel);
+ d->maxLevel = maxLevel;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
+}
+
+/*!
+ Returns the mipmap maximum level used for all texture lookups with this texture.
+
+ \sa setMipMaxLevel(), mipBaseLevel(), mipLevelRange()
+*/
+int QOpenGLTexture::mipMaxLevel() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->maxLevel;
+}
+
+/*!
+ Sets the range of mipmap levels that can be used for texture lookups with this texture
+ to range from \a baseLevel to \a maxLevel.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa setMipBaseLevel(), setMipMaxLevel(), mipLevelRange()
+*/
+void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (!d->features.testFlag(TextureMipMapLevel)) {
+ qWarning("QOpenGLTexture::setMipLevelRange: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
+ return;
+ }
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(baseLevel <= maxLevel);
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
+}
+
+/*!
+ Returns the range of mipmap levels that can be used for texture lookups with this texture.
+
+ \sa mipBaseLevel(), mipMaxLevel()
+*/
+QPair<int, int> QOpenGLTexture::mipLevelRange() const
+{
+ Q_D(const QOpenGLTexture);
+ return qMakePair(d->baseLevel, d->maxLevel);
+}
+
+/*!
+ If \a enabled is \c true, enables automatic mipmap generation for this texture object
+ to occur whenever the level 0 mipmap data is set via setData().
+
+ The automatic mipmap generation is enabled by default.
+
+ \note Mipmap generation is not supported for compressed textures with OpenGL ES 2.0.
+
+ \sa isAutoMipMapGenerationEnabled(), generateMipMaps()
+*/
+void QOpenGLTexture::setAutoMipMapGenerationEnabled(bool enabled)
+{
+ Q_D(QOpenGLTexture);
+ d->autoGenerateMipMaps = enabled;
+}
+
+/*!
+ Returns whether auto mipmap generation is enabled for this texture object.
+
+ \sa setAutoMipMapGenerationEnabled(), generateMipMaps()
+*/
+bool QOpenGLTexture::isAutoMipMapGenerationEnabled() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->autoGenerateMipMaps;
+}
+
+/*!
+ Generates mipmaps for this texture object from mipmap level 0. If you are
+ using a texture target and filtering option that requires mipmaps and you
+ have disabled automatic mipmap generation then you need to call this function
+ or the overload to create the mipmap chain.
+
+ \note Mipmap generation is not supported for compressed textures with OpenGL ES.
+
+ \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
+*/
+void QOpenGLTexture::generateMipMaps()
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (isCompressedFormat(d->format)) {
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
+ if (ctx->isOpenGLES())
+ return;
+ }
+ d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
+}
+
+/*!
+ Generates mipmaps for this texture object from mipmap level \a baseLevel. If you are
+ using a texture target and filtering option that requires mipmaps and you
+ have disabled automatic mipmap generation then you need to call this function
+ or the overload to create the mipmap chain.
+
+ The generation of mipmaps to above \a baseLevel is achieved by setting the mipmap
+ base level to \a baseLevel and then generating the mipmap chain. If \a resetBaseLevel
+ is \c true, then the baseLevel of the texture will be reset to its previous value.
+
+ \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
+*/
+void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel)
+{
+ Q_D(QOpenGLTexture);
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (isCompressedFormat(d->format)) {
+ if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
+ if (ctx->isOpenGLES())
+ return;
+ }
+ int oldBaseLevel;
+ if (resetBaseLevel)
+ oldBaseLevel = mipBaseLevel();
+ setMipBaseLevel(baseLevel);
+ d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
+ if (resetBaseLevel)
+ setMipBaseLevel(oldBaseLevel);
+}
+
+/*!
+ GLSL shaders are able to reorder the components of the vec4 returned by texture
+ functions. It is also desirable to be able to control this reordering from CPU
+ side code. This is made possible by swizzle masks since OpenGL 3.3.
+
+ Each component of the texture can be mapped to one of the SwizzleValue options.
+
+ This function maps \a component to the output \a value.
+
+ \note This function has no effect on Mac and Qt built for OpenGL ES 2.
+ \sa swizzleMask()
+*/
+void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue value)
+{
+#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (!d->features.testFlag(Swizzle)) {
+ qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
+ return;
+ }
+ d->swizzleMask[component - SwizzleRed] = value;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, component, value);
+ return;
+ }
+#else
+ Q_UNUSED(component);
+ Q_UNUSED(value);
+#endif
+ qWarning("QOpenGLTexture: Texture swizzling is not supported");
+}
+
+/*!
+ Parameters \a {r}, \a {g}, \a {b}, and \a {a} are values used for setting
+ the colors red, green, blue, and the alpha value.
+ \overload
+*/
+void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g,
+ SwizzleValue b, SwizzleValue a)
+{
+#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (!d->features.testFlag(Swizzle)) {
+ qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
+ return;
+ }
+ GLint swizzleMask[] = {GLint(r), GLint(g), GLint(b), GLint(a)};
+ d->swizzleMask[0] = r;
+ d->swizzleMask[1] = g;
+ d->swizzleMask[2] = b;
+ d->swizzleMask[3] = a;
+ d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
+ return;
+ }
+#else
+ Q_UNUSED(r);
+ Q_UNUSED(g);
+ Q_UNUSED(b);
+ Q_UNUSED(a);
+#endif
+ qWarning("QOpenGLTexture: Texture swizzling is not supported");
+}
+
+/*!
+ Returns the swizzle mask for texture \a component.
+*/
+QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent component) const
+{
+ Q_D(const QOpenGLTexture);
+ return d->swizzleMask[component - SwizzleRed];
+}
+
+/*!
+ \enum QOpenGLTexture::DepthStencilMode
+ \since 5.4
+ This enum specifies which component of a depth/stencil texture is
+ accessed when the texture is sampled.
+
+ \value DepthMode Equivalent to GL_DEPTH_COMPONENT.
+ \value StencilMode Equivalent to GL_STENCIL_INDEX.
+*/
+
+/*!
+ If using a texture that has a combined depth/stencil format this function sets
+ which component of the texture is accessed to \a mode.
+
+ When the parameter is set to DepthMode, then accessing it from the
+ shader will access the depth component as a single float, as normal. But when
+ the parameter is set to StencilMode, the shader will access the stencil component.
+
+ \note This function has no effect on Mac and Qt built for OpenGL ES 2.
+ \since 5.4
+ \sa depthStencilMode()
+*/
+void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode)
+{
+#if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (!d->features.testFlag(StencilTexturing)) {
+ qWarning("QOpenGLTexture::setDepthStencilMode() requires OpenGL >= 4.3 or GL_ARB_stencil_texturing");
+ return;
+ }
+ d->depthStencilMode = mode;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_DEPTH_STENCIL_TEXTURE_MODE, mode);
+ return;
+ }
+#else
+ Q_UNUSED(mode);
+#endif
+ qWarning("QOpenGLTexture: DepthStencil Mode is not supported");
+}
+
+/*!
+ Returns the depth stencil mode for textures using a combined depth/stencil format.
+
+ \since 5.4
+ \sa setDepthStencilMode()
+*/
+QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->depthStencilMode;
+}
+
+/*!
+ \enum QOpenGLTexture::ComparisonFunction
+ \since 5.5
+ This enum specifies which comparison operator is used when texture comparison
+ is enabled on this texture.
+
+ \value CompareLessEqual Equivalent to GL_LEQUAL.
+ \value CompareGreaterEqual Equivalent to GL_GEQUAL.
+ \value CompareLess Equivalent to GL_LESS.
+ \value CompareGreater Equivalent to GL_GREATER.
+ \value CompareEqual Equivalent to GL_EQUAL.
+ \value CommpareNotEqual Equivalent to GL_NOTEQUAL.
+ \value CompareAlways Equivalent to GL_ALWAYS.
+ \value CompareNever Equivalent to GL_NEVER.
+
+*/
+
+/*!
+ \since 5.5
+
+ Sets the texture comparison function on this texture to \a function. The texture
+ comparison function is used by shadow samplers when sampling a depth texture.
+
+ \sa comparisonFunction()
+*/
+void QOpenGLTexture::setComparisonFunction(QOpenGLTexture::ComparisonFunction function)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (!d->features.testFlag(TextureComparisonOperators)) {
+ qWarning("QOpenGLTexture::setComparisonFunction: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
+ return;
+ }
+ d->comparisonFunction = function;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_FUNC, function);
+}
+
+/*!
+ \since 5.5
+
+ Returns the texture comparison operator set on this texture. By default, a
+ texture has a CompareLessEqual comparison function.
+
+ \sa setComparisonFunction()
+*/
+QOpenGLTexture::ComparisonFunction QOpenGLTexture::comparisonFunction() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->comparisonFunction;
+}
+
+/*!
+ \enum QOpenGLTexture::ComparisonMode
+ \since 5.5
+ This enum specifies which comparison mode is used when sampling this texture.
+
+ \value CompareRefToTexture Equivalent to GL_COMPARE_REF_TO_TEXTURE.
+ \value CompareNone Equivalent to GL_NONE.
+*/
+
+/*!
+ \since 5.5
+
+ Sets the texture comparison mode on this texture to \a mode. The texture
+ comparison mode is used by shadow samplers when sampling a depth texture.
+
+ \sa comparisonMode()
+*/
+void QOpenGLTexture::setComparisonMode(QOpenGLTexture::ComparisonMode mode)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ if (!d->features.testFlag(TextureComparisonOperators)) {
+ qWarning("QOpenGLTexture::setComparisonMode: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
+ return;
+ }
+ d->comparisonMode = mode;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_MODE, mode);
+}
+
+/*!
+ \since 5.5
+
+ Returns the texture comparison mode set on this texture. By default, a
+ texture has a CompareNone comparison mode (i.e. comparisons are disabled).
+
+ \sa setComparisonMode()
+*/
+QOpenGLTexture::ComparisonMode QOpenGLTexture::comparisonMode() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->comparisonMode;
+}
+
+/*!
+ Sets the filter used for minification to \a filter.
+
+ \sa minificationFilter(), setMagnificationFilter(), setMinMagFilters()
+*/
+void QOpenGLTexture::setMinificationFilter(QOpenGLTexture::Filter filter)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->minFilter = filter;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, filter);
+}
+
+/*!
+ Returns the minification filter.
+
+ \sa setMinificationFilter()
+*/
+QOpenGLTexture::Filter QOpenGLTexture::minificationFilter() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->minFilter;
+}
+
+/*!
+ Sets the magnification filter to \a filter.
+
+ \sa magnificationFilter(), setMinificationFilter(), setMinMagFilters()
+*/
+void QOpenGLTexture::setMagnificationFilter(QOpenGLTexture::Filter filter)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->magFilter = filter;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, filter);
+}
+
+/*!
+ Returns the magnification filter.
+
+ \sa setMagnificationFilter()
+*/
+QOpenGLTexture::Filter QOpenGLTexture::magnificationFilter() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->magFilter;
+}
+
+/*!
+ Sets the minification filter to \a minificationFilter and the magnification filter
+ to \a magnificationFilter.
+
+ \sa minMagFilters(), setMinificationFilter(), setMagnificationFilter()
+*/
+void QOpenGLTexture::setMinMagFilters(QOpenGLTexture::Filter minificationFilter,
+ QOpenGLTexture::Filter magnificationFilter)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->minFilter = minificationFilter;
+ d->magFilter = magnificationFilter;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, minificationFilter);
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, magnificationFilter);
+}
+
+/*!
+ Returns the current minification and magnification filters.
+
+ \sa setMinMagFilters()
+*/
+QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter> QOpenGLTexture::minMagFilters() const
+{
+ Q_D(const QOpenGLTexture);
+ return QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter>(d->minFilter, d->magFilter);
+}
+
+/*!
+ If your OpenGL implementation supports the GL_EXT_texture_filter_anisotropic extension
+ this function sets the maximum anisotropy level to \a anisotropy.
+
+ \sa maximumAnisotropy()
+*/
+void QOpenGLTexture::setMaximumAnisotropy(float anisotropy)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ if (!d->features.testFlag(AnisotropicFiltering)) {
+ qWarning("QOpenGLTexture::setMaximumAnisotropy() requires GL_EXT_texture_filter_anisotropic");
+ return;
+ }
+ d->maxAnisotropy = anisotropy;
+ d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
+}
+
+/*!
+ Returns the maximum level of anisotropy to be accounted for when performing texture lookups.
+ This requires the GL_EXT_texture_filter_anisotropic extension.
+
+ \sa setMaximumAnisotropy()
+*/
+float QOpenGLTexture::maximumAnisotropy() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->maxAnisotropy;
+}
+
+/*!
+ Sets the wrap (or repeat mode) for all texture dimentions to \a mode.
+
+ \sa wrapMode()
+*/
+void QOpenGLTexture::setWrapMode(QOpenGLTexture::WrapMode mode)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->setWrapMode(mode);
+}
+
+/*!
+ Holds the texture dimension \a direction.
+ \overload
+*/
+void QOpenGLTexture::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
+{
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->setWrapMode(direction, mode);
+}
+
+/*!
+ Returns the wrap mode for the texture dimension \a direction.
+
+ \sa setWrapMode()
+*/
+QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
+{
+ Q_D(const QOpenGLTexture);
+ return d->wrapMode(direction);
+}
+
+/*!
+ Sets the border color of the texture to \a color.
+
+ \note This function has no effect on Mac and Qt built for OpenGL ES 2.
+ \sa borderColor()
+*/
+void QOpenGLTexture::setBorderColor(const QColor &color)
+{
+ setBorderColor(static_cast<float>(color.redF()), static_cast<float>(color.greenF()),
+ static_cast<float>(color.blueF()), static_cast<float>(color.alphaF()));
+}
+
+/*!
+ Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and \a {a} to the
+ alpha value.
+ \overload
+*/
+void QOpenGLTexture::setBorderColor(float r, float g, float b, float a)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ float values[4];
+ values[0] = r;
+ values[1] = g;
+ values[2] = b;
+ values[3] = a;
+ d->borderColor.clear();
+ for (int i = 0; i < 4; ++i)
+ d->borderColor.append(QVariant(values[i]));
+ d->texFuncs->glTextureParameterfv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
+ return;
+ }
+#else
+ Q_UNUSED(r);
+ Q_UNUSED(g);
+ Q_UNUSED(b);
+ Q_UNUSED(a);
+#endif
+ qWarning("QOpenGLTexture: Border color is not supported");
+}
+
+/*!
+ Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
+ value to \a {a}.
+ \overload
+*/
+void QOpenGLTexture::setBorderColor(int r, int g, int b, int a)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ int values[4];
+ values[0] = r;
+ values[1] = g;
+ values[2] = b;
+ values[3] = a;
+ d->borderColor.clear();
+ for (int i = 0; i < 4; ++i)
+ d->borderColor.append(QVariant(values[i]));
+ d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
+ return;
+ }
+#else
+ Q_UNUSED(r);
+ Q_UNUSED(g);
+ Q_UNUSED(b);
+ Q_UNUSED(a);
+#endif
+ qWarning("QOpenGLTexture: Border color is not supported");
+
+ // TODO Handle case of using glTextureParameterIiv() based on format
+}
+
+/*!
+ Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
+ value to \a {a}.
+ \overload
+*/
+void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ int values[4];
+ values[0] = int(r);
+ values[1] = int(g);
+ values[2] = int(b);
+ values[3] = int(a);
+ d->borderColor.clear();
+ for (int i = 0; i < 4; ++i)
+ d->borderColor.append(QVariant(values[i]));
+ d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
+ return;
+ }
+#else
+ Q_UNUSED(r);
+ Q_UNUSED(g);
+ Q_UNUSED(b);
+ Q_UNUSED(a);
+#endif
+ qWarning("QOpenGLTexture: Border color is not supported");
+
+ // TODO Handle case of using glTextureParameterIuiv() based on format
+}
+
+/*!
+ Returns the borderColor of this texture.
+
+ \sa setBorderColor()
+*/
+QColor QOpenGLTexture::borderColor() const
+{
+ Q_D(const QOpenGLTexture);
+ QColor c(0.0f, 0.0f, 0.0f, 0.0f);
+ if (!d->borderColor.isEmpty()) {
+ c.setRedF(d->borderColor.at(0).toFloat());
+ c.setGreenF(d->borderColor.at(1).toFloat());
+ c.setBlueF(d->borderColor.at(2).toFloat());
+ c.setAlphaF(d->borderColor.at(3).toFloat());
+ }
+ return c;
+}
+
+/*!
+ Writes the texture border color into the first four elements
+ of the array pointed to by \a border.
+
+ \sa setBorderColor()
+*/
+void QOpenGLTexture::borderColor(float *border) const
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(border);
+ if (d->borderColor.isEmpty()) {
+ for (int i = 0; i < 4; ++i)
+ border[i] = 0.0f;
+ } else {
+ for (int i = 0; i < 4; ++i)
+ border[i] = d->borderColor.at(i).toFloat();
+ }
+}
+
+/*!
+ Writes the texture border color into the first four elements
+ of the array pointed to by \a border.
+
+ \overload
+*/
+void QOpenGLTexture::borderColor(int *border) const
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(border);
+ if (d->borderColor.isEmpty()) {
+ for (int i = 0; i < 4; ++i)
+ border[i] = 0;
+ } else {
+ for (int i = 0; i < 4; ++i)
+ border[i] = d->borderColor.at(i).toInt();
+ }
+}
+
+/*!
+ Writes the texture border color into the first four elements
+ of the array pointed to by \a border.
+
+ \overload
+*/
+void QOpenGLTexture::borderColor(unsigned int *border) const
+{
+ Q_D(const QOpenGLTexture);
+ Q_ASSERT(border);
+ if (d->borderColor.isEmpty()) {
+ for (int i = 0; i < 4; ++i)
+ border[i] = 0;
+ } else {
+ for (int i = 0; i < 4; ++i)
+ border[i] = d->borderColor.at(i).toUInt();
+ }
+}
+
+/*!
+ Sets the minimum level of detail to \a value. This limits the selection of highest
+ resolution mipmap (lowest mipmap level). The default value is -1000.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa minimumLevelOfDetail(), setMaximumLevelOfDetail(), setLevelOfDetailRange()
+*/
+void QOpenGLTexture::setMinimumLevelOfDetail(float value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(value < d->maxLevelOfDetail);
+ d->minLevelOfDetail = value;
+ d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, value);
+ return;
+ }
+#else
+ Q_UNUSED(value);
+#endif
+ qWarning("QOpenGLTexture: Detail level is not supported");
+}
+
+/*!
+ Returns the minimum level of detail parameter.
+
+ \sa setMinimumLevelOfDetail(), maximumLevelOfDetail(), levelOfDetailRange()
+*/
+float QOpenGLTexture::minimumLevelOfDetail() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->minLevelOfDetail;
+}
+
+/*!
+ Sets the maximum level of detail to \a value. This limits the selection of lowest
+ resolution mipmap (highest mipmap level). The default value is 1000.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa maximumLevelOfDetail(), setMinimumLevelOfDetail(), setLevelOfDetailRange()
+*/
+void QOpenGLTexture::setMaximumLevelOfDetail(float value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(value > d->minLevelOfDetail);
+ d->maxLevelOfDetail = value;
+ d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, value);
+ return;
+ }
+#else
+ Q_UNUSED(value);
+#endif
+ qWarning("QOpenGLTexture: Detail level is not supported");
+}
+
+/*!
+ Returns the maximum level of detail parameter.
+
+ \sa setMaximumLevelOfDetail(), minimumLevelOfDetail(), levelOfDetailRange()
+*/
+float QOpenGLTexture::maximumLevelOfDetail() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->maxLevelOfDetail;
+}
+
+/*!
+ Sets the minimum level of detail parameters to \a min and the maximum level
+ to \a max.
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa levelOfDetailRange(), setMinimumLevelOfDetail(), setMaximumLevelOfDetail()
+*/
+void QOpenGLTexture::setLevelOfDetailRange(float min, float max)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ Q_ASSERT(min < max);
+ d->minLevelOfDetail = min;
+ d->maxLevelOfDetail = max;
+ d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, min);
+ d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, max);
+ return;
+ }
+#else
+ Q_UNUSED(min);
+ Q_UNUSED(max);
+#endif
+ qWarning("QOpenGLTexture: Detail level is not supported");
+}
+
+/*!
+ Returns the minimum and maximum level of detail parameters.
+
+ \sa setLevelOfDetailRange(), minimumLevelOfDetail(), maximumLevelOfDetail()
+*/
+QPair<float, float> QOpenGLTexture::levelOfDetailRange() const
+{
+ Q_D(const QOpenGLTexture);
+ return qMakePair(d->minLevelOfDetail, d->maxLevelOfDetail);
+}
+
+/*!
+ Sets the level of detail bias to \a bias.
+ Level of detail bias affects the point at which mipmapping levels change.
+ Increasing values for level of detail bias makes the overall images blurrier
+ or smoother. Decreasing values make the overall images sharper.
+
+ \note This function has no effect on Qt built for OpenGL ES 2.
+ \sa levelofDetailBias()
+*/
+void QOpenGLTexture::setLevelofDetailBias(float bias)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!QOpenGLContext::currentContext()->isOpenGLES()) {
+ Q_D(QOpenGLTexture);
+ d->create();
+ Q_ASSERT(d->texFuncs);
+ Q_ASSERT(d->textureId);
+ d->levelOfDetailBias = bias;
+ d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_LOD_BIAS, bias);
+ return;
+ }
+#else
+ Q_UNUSED(bias);
+#endif
+ qWarning("QOpenGLTexture: Detail level is not supported");
+}
+
+/*!
+ Returns the level of detail bias parameter.
+
+ \sa setLevelofDetailBias()
+*/
+float QOpenGLTexture::levelofDetailBias() const
+{
+ Q_D(const QOpenGLTexture);
+ return d->levelOfDetailBias;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QOpenGLTexture *t)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QOpenGLTexture(";
+ if (t) {
+ const QOpenGLTexturePrivate *d = t->d_ptr.data();
+ debug << d->target << ", bindingTarget=" << d->bindingTarget
+ << ", size=[" << d->dimensions[0]
+ << ", " << d->dimensions[1];
+ if (d->target == QOpenGLTexture::Target3D)
+ debug << ", " << d->dimensions[2];
+ debug << "], format=" << d->format << ", formatClass=" << d->formatClass;
+ if (t->isCreated())
+ debug << ", textureId=" << d->textureId;
+ if (t->isBound())
+ debug << ", [bound]";
+ if (t->isTextureView())
+ debug << ", [view]";
+ if (d->fixedSamplePositions)
+ debug << ", [fixedSamplePositions]";
+ debug << ", mipLevels=" << d->requestedMipLevels << ", layers=" << d->layers
+ << ", faces=" << d->faces << ", samples=" << d->samples
+ << ", depthStencilMode=" << d->depthStencilMode << ", comparisonFunction="
+ << d->comparisonFunction << ", comparisonMode=" << d->comparisonMode
+ << ", features=" << d->features << ", minificationFilter=" << d->minFilter
+ << ", magnificationFilter=" << d->magFilter << ", wrapMode=" << d->wrapModes[0];
+ } else {
+ debug << '0';
+ }
+ debug << ')';
+ return debug;
+}
+#endif // QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopengltexture.h b/src/opengl/qopengltexture.h
new file mode 100644
index 0000000000..8eba2724df
--- /dev/null
+++ b/src/opengl/qopengltexture.h
@@ -0,0 +1,663 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QOPENGLABSTRACTTEXTURE_H
+#define QOPENGLABSTRACTTEXTURE_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#ifndef QT_NO_OPENGL
+
+#include <QtGui/qopengl.h>
+#include <QtGui/qimage.h>
+#include <QtCore/QScopedPointer>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+class QOpenGLTexturePrivate;
+class QOpenGLPixelTransferOptions;
+
+class Q_OPENGL_EXPORT QOpenGLTexture
+{
+ Q_GADGET
+public:
+ enum Target {
+ Target1D = 0x0DE0, // GL_TEXTURE_1D
+ Target1DArray = 0x8C18, // GL_TEXTURE_1D_ARRAY
+ Target2D = 0x0DE1, // GL_TEXTURE_2D
+ Target2DArray = 0x8C1A, // GL_TEXTURE_2D_ARRAY
+ Target3D = 0x806F, // GL_TEXTURE_3D
+ TargetCubeMap = 0x8513, // GL_TEXTURE_CUBE_MAP
+ TargetCubeMapArray = 0x9009, // GL_TEXTURE_CUBE_MAP_ARRAY
+ Target2DMultisample = 0x9100, // GL_TEXTURE_2D_MULTISAMPLE
+ Target2DMultisampleArray = 0x9102, // GL_TEXTURE_2D_MULTISAMPLE_ARRAY
+ TargetRectangle = 0x84F5, // GL_TEXTURE_RECTANGLE
+ TargetBuffer = 0x8C2A // GL_TEXTURE_BUFFER
+ };
+ Q_ENUM(Target)
+
+ enum BindingTarget {
+ BindingTarget1D = 0x8068, // GL_TEXTURE_BINDING_1D
+ BindingTarget1DArray = 0x8C1C, // GL_TEXTURE_BINDING_1D_ARRAY
+ BindingTarget2D = 0x8069, // GL_TEXTURE_BINDING_2D
+ BindingTarget2DArray = 0x8C1D, // GL_TEXTURE_BINDING_2D_ARRAY
+ BindingTarget3D = 0x806A, // GL_TEXTURE_BINDING_3D
+ BindingTargetCubeMap = 0x8514, // GL_TEXTURE_BINDING_CUBE_MAP
+ BindingTargetCubeMapArray = 0x900A, // GL_TEXTURE_BINDING_CUBE_MAP_ARRAY
+ BindingTarget2DMultisample = 0x9104, // GL_TEXTURE_BINDING_2D_MULTISAMPLE
+ BindingTarget2DMultisampleArray = 0x9105, // GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
+ BindingTargetRectangle = 0x84F6, // GL_TEXTURE_BINDING_RECTANGLE
+ BindingTargetBuffer = 0x8C2C // GL_TEXTURE_BINDING_BUFFER
+ };
+ Q_ENUM(BindingTarget)
+
+ enum MipMapGeneration {
+ GenerateMipMaps,
+ DontGenerateMipMaps
+ };
+ Q_ENUM(MipMapGeneration)
+
+ enum TextureUnitReset {
+ ResetTextureUnit,
+ DontResetTextureUnit
+ };
+ Q_ENUM(TextureUnitReset)
+
+ enum TextureFormat {
+ NoFormat = 0, // GL_NONE
+
+ // Unsigned normalized formats
+ R8_UNorm = 0x8229, // GL_R8
+ RG8_UNorm = 0x822B, // GL_RG8
+ RGB8_UNorm = 0x8051, // GL_RGB8
+ RGBA8_UNorm = 0x8058, // GL_RGBA8
+
+ R16_UNorm = 0x822A, // GL_R16
+ RG16_UNorm = 0x822C, // GL_RG16
+ RGB16_UNorm = 0x8054, // GL_RGB16
+ RGBA16_UNorm = 0x805B, // GL_RGBA16
+
+ // Signed normalized formats
+ R8_SNorm = 0x8F94, // GL_R8_SNORM
+ RG8_SNorm = 0x8F95, // GL_RG8_SNORM
+ RGB8_SNorm = 0x8F96, // GL_RGB8_SNORM
+ RGBA8_SNorm = 0x8F97, // GL_RGBA8_SNORM
+
+ R16_SNorm = 0x8F98, // GL_R16_SNORM
+ RG16_SNorm = 0x8F99, // GL_RG16_SNORM
+ RGB16_SNorm = 0x8F9A, // GL_RGB16_SNORM
+ RGBA16_SNorm = 0x8F9B, // GL_RGBA16_SNORM
+
+ // Unsigned integer formats
+ R8U = 0x8232, // GL_R8UI
+ RG8U = 0x8238, // GL_RG8UI
+ RGB8U = 0x8D7D, // GL_RGB8UI
+ RGBA8U = 0x8D7C, // GL_RGBA8UI
+
+ R16U = 0x8234, // GL_R16UI
+ RG16U = 0x823A, // GL_RG16UI
+ RGB16U = 0x8D77, // GL_RGB16UI
+ RGBA16U = 0x8D76, // GL_RGBA16UI
+
+ R32U = 0x8236, // GL_R32UI
+ RG32U = 0x823C, // GL_RG32UI
+ RGB32U = 0x8D71, // GL_RGB32UI
+ RGBA32U = 0x8D70, // GL_RGBA32UI
+
+ // Signed integer formats
+ R8I = 0x8231, // GL_R8I
+ RG8I = 0x8237, // GL_RG8I
+ RGB8I = 0x8D8F, // GL_RGB8I
+ RGBA8I = 0x8D8E, // GL_RGBA8I
+
+ R16I = 0x8233, // GL_R16I
+ RG16I = 0x8239, // GL_RG16I
+ RGB16I = 0x8D89, // GL_RGB16I
+ RGBA16I = 0x8D88, // GL_RGBA16I
+
+ R32I = 0x8235, // GL_R32I
+ RG32I = 0x823B, // GL_RG32I
+ RGB32I = 0x8D83, // GL_RGB32I
+ RGBA32I = 0x8D82, // GL_RGBA32I
+
+ // Floating point formats
+ R16F = 0x822D, // GL_R16F
+ RG16F = 0x822F, // GL_RG16F
+ RGB16F = 0x881B, // GL_RGB16F
+ RGBA16F = 0x881A, // GL_RGBA16F
+
+ R32F = 0x822E, // GL_R32F
+ RG32F = 0x8230, // GL_RG32F
+ RGB32F = 0x8815, // GL_RGB32F
+ RGBA32F = 0x8814, // GL_RGBA32F
+
+ // Packed formats
+ RGB9E5 = 0x8C3D, // GL_RGB9_E5
+ RG11B10F = 0x8C3A, // GL_R11F_G11F_B10F
+ RG3B2 = 0x2A10, // GL_R3_G3_B2
+ R5G6B5 = 0x8D62, // GL_RGB565
+ RGB5A1 = 0x8057, // GL_RGB5_A1
+ RGBA4 = 0x8056, // GL_RGBA4
+ RGB10A2 = 0x906F, // GL_RGB10_A2UI
+
+ // Depth formats
+ D16 = 0x81A5, // GL_DEPTH_COMPONENT16
+ D24 = 0x81A6, // GL_DEPTH_COMPONENT24
+ D24S8 = 0x88F0, // GL_DEPTH24_STENCIL8
+ D32 = 0x81A7, // GL_DEPTH_COMPONENT32
+ D32F = 0x8CAC, // GL_DEPTH_COMPONENT32F
+ D32FS8X24 = 0x8CAD, // GL_DEPTH32F_STENCIL8
+ S8 = 0x8D48, // GL_STENCIL_INDEX8
+
+ // Compressed formats
+ RGB_DXT1 = 0x83F0, // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
+ RGBA_DXT1 = 0x83F1, // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ RGBA_DXT3 = 0x83F2, // GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
+ RGBA_DXT5 = 0x83F3, // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
+ R_ATI1N_UNorm = 0x8DBB, // GL_COMPRESSED_RED_RGTC1
+ R_ATI1N_SNorm = 0x8DBC, // GL_COMPRESSED_SIGNED_RED_RGTC1
+ RG_ATI2N_UNorm = 0x8DBD, // GL_COMPRESSED_RG_RGTC2
+ RG_ATI2N_SNorm = 0x8DBE, // GL_COMPRESSED_SIGNED_RG_RGTC2
+ RGB_BP_UNSIGNED_FLOAT = 0x8E8F, // GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
+ RGB_BP_SIGNED_FLOAT = 0x8E8E, // GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
+ RGB_BP_UNorm = 0x8E8C, // GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
+ R11_EAC_UNorm = 0x9270, // GL_COMPRESSED_R11_EAC
+ R11_EAC_SNorm = 0x9271, // GL_COMPRESSED_SIGNED_R11_EAC
+ RG11_EAC_UNorm = 0x9272, // GL_COMPRESSED_RG11_EAC
+ RG11_EAC_SNorm = 0x9273, // GL_COMPRESSED_SIGNED_RG11_EAC
+ RGB8_ETC2 = 0x9274, // GL_COMPRESSED_RGB8_ETC2
+ SRGB8_ETC2 = 0x9275, // GL_COMPRESSED_SRGB8_ETC2
+ RGB8_PunchThrough_Alpha1_ETC2 = 0x9276, // GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ SRGB8_PunchThrough_Alpha1_ETC2 = 0x9277, // GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
+ RGBA8_ETC2_EAC = 0x9278, // GL_COMPRESSED_RGBA8_ETC2_EAC
+ SRGB8_Alpha8_ETC2_EAC = 0x9279, // GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
+ RGB8_ETC1 = 0x8D64, // GL_ETC1_RGB8_OES
+ RGBA_ASTC_4x4 = 0x93B0, // GL_COMPRESSED_RGBA_ASTC_4x4_KHR
+ RGBA_ASTC_5x4 = 0x93B1, // GL_COMPRESSED_RGBA_ASTC_5x4_KHR
+ RGBA_ASTC_5x5 = 0x93B2, // GL_COMPRESSED_RGBA_ASTC_5x5_KHR
+ RGBA_ASTC_6x5 = 0x93B3, // GL_COMPRESSED_RGBA_ASTC_6x5_KHR
+ RGBA_ASTC_6x6 = 0x93B4, // GL_COMPRESSED_RGBA_ASTC_6x6_KHR
+ RGBA_ASTC_8x5 = 0x93B5, // GL_COMPRESSED_RGBA_ASTC_8x5_KHR
+ RGBA_ASTC_8x6 = 0x93B6, // GL_COMPRESSED_RGBA_ASTC_8x6_KHR
+ RGBA_ASTC_8x8 = 0x93B7, // GL_COMPRESSED_RGBA_ASTC_8x8_KHR
+ RGBA_ASTC_10x5 = 0x93B8, // GL_COMPRESSED_RGBA_ASTC_10x5_KHR
+ RGBA_ASTC_10x6 = 0x93B9, // GL_COMPRESSED_RGBA_ASTC_10x6_KHR
+ RGBA_ASTC_10x8 = 0x93BA, // GL_COMPRESSED_RGBA_ASTC_10x8_KHR
+ RGBA_ASTC_10x10 = 0x93BB, // GL_COMPRESSED_RGBA_ASTC_10x10_KHR
+ RGBA_ASTC_12x10 = 0x93BC, // GL_COMPRESSED_RGBA_ASTC_12x10_KHR
+ RGBA_ASTC_12x12 = 0x93BD, // GL_COMPRESSED_RGBA_ASTC_12x12_KHR
+ SRGB8_Alpha8_ASTC_4x4 = 0x93D0, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
+ SRGB8_Alpha8_ASTC_5x4 = 0x93D1, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
+ SRGB8_Alpha8_ASTC_5x5 = 0x93D2, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
+ SRGB8_Alpha8_ASTC_6x5 = 0x93D3, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
+ SRGB8_Alpha8_ASTC_6x6 = 0x93D4, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
+ SRGB8_Alpha8_ASTC_8x5 = 0x93D5, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
+ SRGB8_Alpha8_ASTC_8x6 = 0x93D6, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
+ SRGB8_Alpha8_ASTC_8x8 = 0x93D7, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
+ SRGB8_Alpha8_ASTC_10x5 = 0x93D8, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
+ SRGB8_Alpha8_ASTC_10x6 = 0x93D9, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
+ SRGB8_Alpha8_ASTC_10x8 = 0x93DA, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
+ SRGB8_Alpha8_ASTC_10x10 = 0x93DB, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
+ SRGB8_Alpha8_ASTC_12x10 = 0x93DC, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
+ SRGB8_Alpha8_ASTC_12x12 = 0x93DD, // GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
+
+ // sRGB formats
+ SRGB8 = 0x8C41, // GL_SRGB8
+ SRGB8_Alpha8 = 0x8C43, // GL_SRGB8_ALPHA8
+ SRGB_DXT1 = 0x8C4C, // GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
+ SRGB_Alpha_DXT1 = 0x8C4D, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
+ SRGB_Alpha_DXT3 = 0x8C4E, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
+ SRGB_Alpha_DXT5 = 0x8C4F, // GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
+ SRGB_BP_UNorm = 0x8E8D, // GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
+
+ // ES 2 formats
+ DepthFormat = 0x1902, // GL_DEPTH_COMPONENT
+ AlphaFormat = 0x1906, // GL_ALPHA
+ RGBFormat = 0x1907, // GL_RGB
+ RGBAFormat = 0x1908, // GL_RGBA
+ LuminanceFormat = 0x1909, // GL_LUMINANCE
+ LuminanceAlphaFormat = 0x190A
+
+ };
+ Q_ENUM(TextureFormat)
+
+ // This is not used externally yet but is reserved to allow checking of
+ // compatibility between texture formats
+#ifndef Q_QDOC
+ enum TextureFormatClass {
+ NoFormatClass,
+ FormatClass_128Bit,
+ FormatClass_96Bit,
+ FormatClass_64Bit,
+ FormatClass_48Bit,
+ FormatClass_32Bit,
+ FormatClass_24Bit,
+ FormatClass_16Bit,
+ FormatClass_8Bit,
+ FormatClass_RGTC1_R,
+ FormatClass_RGTC2_RG,
+ FormatClass_BPTC_Unorm,
+ FormatClass_BPTC_Float,
+ FormatClass_S3TC_DXT1_RGB,
+ FormatClass_S3TC_DXT1_RGBA,
+ FormatClass_S3TC_DXT3_RGBA,
+ FormatClass_S3TC_DXT5_RGBA,
+ FormatClass_Unique
+ };
+#endif
+
+ enum CubeMapFace {
+ CubeMapPositiveX = 0x8515, // GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ CubeMapNegativeX = 0x8516, // GL_TEXTURE_CUBE_MAP_NEGATIVE_X
+ CubeMapPositiveY = 0x8517, // GL_TEXTURE_CUBE_MAP_POSITIVE_Y
+ CubeMapNegativeY = 0x8518, // GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
+ CubeMapPositiveZ = 0x8519, // GL_TEXTURE_CUBE_MAP_POSITIVE_Z
+ CubeMapNegativeZ = 0x851A // GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+ };
+ Q_ENUM(CubeMapFace)
+
+ enum PixelFormat {
+ NoSourceFormat = 0, // GL_NONE
+ Red = 0x1903, // GL_RED
+ RG = 0x8227, // GL_RG
+ RGB = 0x1907, // GL_RGB
+ BGR = 0x80E0, // GL_BGR
+ RGBA = 0x1908, // GL_RGBA
+ BGRA = 0x80E1, // GL_BGRA
+ Red_Integer = 0x8D94, // GL_RED_INTEGER
+ RG_Integer = 0x8228, // GL_RG_INTEGER
+ RGB_Integer = 0x8D98, // GL_RGB_INTEGER
+ BGR_Integer = 0x8D9A, // GL_BGR_INTEGER
+ RGBA_Integer = 0x8D99, // GL_RGBA_INTEGER
+ BGRA_Integer = 0x8D9B, // GL_BGRA_INTEGER
+ Stencil = 0x1901, // GL_STENCIL_INDEX
+ Depth = 0x1902, // GL_DEPTH_COMPONENT
+ DepthStencil = 0x84F9, // GL_DEPTH_STENCIL
+ Alpha = 0x1906, // GL_ALPHA
+ Luminance = 0x1909, // GL_LUMINANCE
+ LuminanceAlpha = 0x190A // GL_LUMINANCE_ALPHA
+ };
+ Q_ENUM(PixelFormat)
+
+ enum PixelType {
+ NoPixelType = 0, // GL_NONE
+ Int8 = 0x1400, // GL_BYTE
+ UInt8 = 0x1401, // GL_UNSIGNED_BYTE
+ Int16 = 0x1402, // GL_SHORT
+ UInt16 = 0x1403, // GL_UNSIGNED_SHORT
+ Int32 = 0x1404, // GL_INT
+ UInt32 = 0x1405, // GL_UNSIGNED_INT
+ Float16 = 0x140B, // GL_HALF_FLOAT
+ Float16OES = 0x8D61, // GL_HALF_FLOAT_OES
+ Float32 = 0x1406, // GL_FLOAT
+ UInt32_RGB9_E5 = 0x8C3E, // GL_UNSIGNED_INT_5_9_9_9_REV
+ UInt32_RG11B10F = 0x8C3B, // GL_UNSIGNED_INT_10F_11F_11F_REV
+ UInt8_RG3B2 = 0x8032, // GL_UNSIGNED_BYTE_3_3_2
+ UInt8_RG3B2_Rev = 0x8362, // GL_UNSIGNED_BYTE_2_3_3_REV
+ UInt16_RGB5A1 = 0x8034, // GL_UNSIGNED_SHORT_5_5_5_1
+ UInt16_RGB5A1_Rev = 0x8366, // GL_UNSIGNED_SHORT_1_5_5_5_REV
+ UInt16_R5G6B5 = 0x8363, // GL_UNSIGNED_SHORT_5_6_5
+ UInt16_R5G6B5_Rev = 0x8364, // GL_UNSIGNED_SHORT_5_6_5_REV
+ UInt16_RGBA4 = 0x8033, // GL_UNSIGNED_SHORT_4_4_4_4
+ UInt16_RGBA4_Rev = 0x8365, // GL_UNSIGNED_SHORT_4_4_4_4_REV
+ UInt32_RGBA8 = 0x8035, // GL_UNSIGNED_INT_8_8_8_8
+ UInt32_RGBA8_Rev = 0x8367, // GL_UNSIGNED_INT_8_8_8_8_REV
+ UInt32_RGB10A2 = 0x8036, // GL_UNSIGNED_INT_10_10_10_2
+ UInt32_RGB10A2_Rev = 0x8368, // GL_UNSIGNED_INT_2_10_10_10_REV
+ UInt32_D24S8 = 0x84FA, // GL_UNSIGNED_INT_24_8
+ Float32_D32_UInt32_S8_X24 = 0x8DAD // GL_FLOAT_32_UNSIGNED_INT_24_8_REV
+ };
+ Q_ENUM(PixelType)
+
+ enum SwizzleComponent {
+ SwizzleRed = 0x8E42, // GL_TEXTURE_SWIZZLE_R
+ SwizzleGreen = 0x8E43, // GL_TEXTURE_SWIZZLE_G
+ SwizzleBlue = 0x8E44, // GL_TEXTURE_SWIZZLE_B
+ SwizzleAlpha = 0x8E45 // GL_TEXTURE_SWIZZLE_A
+ };
+ Q_ENUM(SwizzleComponent)
+
+ enum SwizzleValue {
+ RedValue = 0x1903, // GL_RED
+ GreenValue = 0x1904, // GL_GREEN
+ BlueValue = 0x1905, // GL_BLUE
+ AlphaValue = 0x1906, // GL_ALPHA
+ ZeroValue = 0, // GL_ZERO
+ OneValue = 1 // GL_ONE
+ };
+ Q_ENUM(SwizzleValue)
+
+ enum WrapMode {
+ Repeat = 0x2901, // GL_REPEAT
+ MirroredRepeat = 0x8370, // GL_MIRRORED_REPEAT
+ ClampToEdge = 0x812F, // GL_CLAMP_TO_EDGE
+ ClampToBorder = 0x812D // GL_CLAMP_TO_BORDER
+ };
+ Q_ENUM(WrapMode)
+
+ enum CoordinateDirection {
+ DirectionS = 0x2802, // GL_TEXTURE_WRAP_S
+ DirectionT = 0x2803, // GL_TEXTURE_WRAP_T
+ DirectionR = 0x8072 // GL_TEXTURE_WRAP_R
+ };
+ Q_ENUM(CoordinateDirection)
+
+ // Features
+ enum Feature {
+ ImmutableStorage = 0x00000001,
+ ImmutableMultisampleStorage = 0x00000002,
+ TextureRectangle = 0x00000004,
+ TextureArrays = 0x00000008,
+ Texture3D = 0x00000010,
+ TextureMultisample = 0x00000020,
+ TextureBuffer = 0x00000040,
+ TextureCubeMapArrays = 0x00000080,
+ Swizzle = 0x00000100,
+ StencilTexturing = 0x00000200,
+ AnisotropicFiltering = 0x00000400,
+ NPOTTextures = 0x00000800,
+ NPOTTextureRepeat = 0x00001000,
+ Texture1D = 0x00002000,
+ TextureComparisonOperators = 0x00004000,
+ TextureMipMapLevel = 0x00008000,
+#ifndef Q_QDOC
+ MaxFeatureFlag = 0x00010000
+#endif
+ };
+ Q_DECLARE_FLAGS(Features, Feature)
+ Q_ENUM(Feature)
+
+ explicit QOpenGLTexture(Target target);
+ explicit QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps);
+ ~QOpenGLTexture();
+
+ Target target() const;
+
+ // Creation and destruction
+ bool create();
+ void destroy();
+ bool isCreated() const;
+ GLuint textureId() const;
+
+ // Binding and releasing
+ void bind();
+ void bind(uint unit, TextureUnitReset reset = DontResetTextureUnit);
+ void release();
+ void release(uint unit, TextureUnitReset reset = DontResetTextureUnit);
+
+ bool isBound() const;
+ bool isBound(uint unit);
+ static GLuint boundTextureId(BindingTarget target);
+ static GLuint boundTextureId(uint unit, BindingTarget target);
+
+ // Storage allocation
+ void setFormat(TextureFormat format);
+ TextureFormat format() const;
+ void setSize(int width, int height = 1, int depth = 1);
+ int width() const;
+ int height() const;
+ int depth() const;
+ void setMipLevels(int levels);
+ int mipLevels() const;
+ int maximumMipLevels() const;
+ void setLayers(int layers);
+ int layers() const;
+ int faces() const;
+ void setSamples(int samples);
+ int samples() const;
+ void setFixedSamplePositions(bool fixed);
+ bool isFixedSamplePositions() const;
+ void allocateStorage();
+ void allocateStorage(PixelFormat pixelFormat, PixelType pixelType);
+ bool isStorageAllocated() const;
+
+ QOpenGLTexture *createTextureView(Target target,
+ TextureFormat viewFormat,
+ int minimumMipmapLevel, int maximumMipmapLevel,
+ int minimumLayer, int maximumLayer) const;
+ bool isTextureView() const;
+
+ // Pixel transfer
+ // ### Qt 6: remove the non-const void * overloads
+#if QT_DEPRECATED_SINCE(5, 3)
+ QT_DEPRECATED void setData(int mipLevel, int layer, CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setData(int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setData(int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setData(PixelFormat sourceFormat, PixelType sourceType,
+ void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+#endif // QT_DEPRECATED_SINCE(5, 3)
+
+ void setData(int mipLevel, int layer, CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int mipLevel, int layer, int layerCount, CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth, int mipLevel,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace cubeFace,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setData(int xOffset, int yOffset, int zOffset,
+ int width, int height, int depth,
+ int mipLevel, int layer,
+ CubeMapFace cubeFace, int layerCount,
+ PixelFormat sourceFormat, PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options = nullptr);
+
+ // Compressed data upload
+ // ### Qt 6: remove the non-const void * overloads
+#if QT_DEPRECATED_SINCE(5, 3)
+ QT_DEPRECATED void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
+ int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setCompressedData(int mipLevel, int layer,
+ int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setCompressedData(int mipLevel, int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ QT_DEPRECATED void setCompressedData(int dataSize, void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+#endif // QT_DEPRECATED_SINCE(5, 3)
+
+ void setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setCompressedData(int mipLevel, int layer, int layerCount, CubeMapFace cubeFace,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setCompressedData(int mipLevel, int layer,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setCompressedData(int mipLevel, int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+ void setCompressedData(int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options = nullptr);
+
+ // Helpful overloads for setData
+ void setData(const QImage& image, MipMapGeneration genMipMaps = GenerateMipMaps);
+
+ static bool hasFeature(Feature feature);
+
+ // Texture Parameters
+ void setMipBaseLevel(int baseLevel);
+ int mipBaseLevel() const;
+ void setMipMaxLevel(int maxLevel);
+ int mipMaxLevel() const;
+ void setMipLevelRange(int baseLevel, int maxLevel);
+ QPair<int, int> mipLevelRange() const;
+
+ void setAutoMipMapGenerationEnabled(bool enabled);
+ bool isAutoMipMapGenerationEnabled() const;
+
+ void generateMipMaps();
+ void generateMipMaps(int baseLevel, bool resetBaseLevel = true);
+
+ void setSwizzleMask(SwizzleComponent component, SwizzleValue value);
+ void setSwizzleMask(SwizzleValue r, SwizzleValue g,
+ SwizzleValue b, SwizzleValue a);
+ SwizzleValue swizzleMask(SwizzleComponent component) const;
+
+ enum DepthStencilMode {
+ DepthMode = 0x1902, // GL_DEPTH_COMPONENT
+ StencilMode = 0x1901 // GL_STENCIL_INDEX
+ };
+ Q_ENUM(DepthStencilMode)
+
+ void setDepthStencilMode(DepthStencilMode mode);
+ DepthStencilMode depthStencilMode() const;
+
+ enum ComparisonFunction {
+ CompareLessEqual = 0x0203, // GL_LEQUAL
+ CompareGreaterEqual = 0x0206, // GL_GEQUAL
+ CompareLess = 0x0201, // GL_LESS
+ CompareGreater = 0x0204, // GL_GREATER
+ CompareEqual = 0x0202, // GL_EQUAL
+ CommpareNotEqual = 0x0205, // GL_NOTEQUAL
+ CompareAlways = 0x0207, // GL_ALWAYS
+ CompareNever = 0x0200 // GL_NEVER
+ };
+ Q_ENUM(ComparisonFunction)
+
+ void setComparisonFunction(ComparisonFunction function);
+ ComparisonFunction comparisonFunction() const;
+
+ enum ComparisonMode {
+ CompareRefToTexture = 0x884E, // GL_COMPARE_REF_TO_TEXTURE
+ CompareNone = 0x0000 // GL_NONE
+ };
+
+ void setComparisonMode(ComparisonMode mode);
+ ComparisonMode comparisonMode() const;
+
+ // Sampling Parameters
+ enum Filter {
+ Nearest = 0x2600, // GL_NEAREST
+ Linear = 0x2601, // GL_LINEAR
+ NearestMipMapNearest = 0x2700, // GL_NEAREST_MIPMAP_NEAREST
+ NearestMipMapLinear = 0x2702, // GL_NEAREST_MIPMAP_LINEAR
+ LinearMipMapNearest = 0x2701, // GL_LINEAR_MIPMAP_NEAREST
+ LinearMipMapLinear = 0x2703 // GL_LINEAR_MIPMAP_LINEAR
+ };
+ Q_ENUM(Filter)
+
+ void setMinificationFilter(Filter filter);
+ Filter minificationFilter() const;
+ void setMagnificationFilter(Filter filter);
+ Filter magnificationFilter() const;
+ void setMinMagFilters(Filter minificationFilter,
+ Filter magnificationFilter);
+ QPair<Filter, Filter> minMagFilters() const;
+ void setMaximumAnisotropy(float anisotropy);
+ float maximumAnisotropy() const;
+
+ void setWrapMode(WrapMode mode);
+ void setWrapMode(CoordinateDirection direction, WrapMode mode);
+ WrapMode wrapMode(CoordinateDirection direction) const;
+
+ void setBorderColor(const QColor &color);
+ void setBorderColor(float r, float g, float b, float a);
+ void setBorderColor(int r, int g, int b, int a);
+ void setBorderColor(uint r, uint g, uint b, uint a);
+
+ QColor borderColor() const;
+ void borderColor(float *border) const;
+ void borderColor(int *border) const;
+ void borderColor(unsigned int *border) const;
+
+ void setMinimumLevelOfDetail(float value);
+ float minimumLevelOfDetail() const;
+ void setMaximumLevelOfDetail(float value);
+ float maximumLevelOfDetail() const;
+ void setLevelOfDetailRange(float min, float max);
+ QPair<float, float> levelOfDetailRange() const;
+ void setLevelofDetailBias(float bias);
+ float levelofDetailBias() const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_OPENGL_EXPORT QDebug operator<<(QDebug dbg, const QOpenGLTexture *t);
+#endif
+
+private:
+ Q_DISABLE_COPY(QOpenGLTexture)
+ Q_DECLARE_PRIVATE(QOpenGLTexture)
+ QScopedPointer<QOpenGLTexturePrivate> d_ptr;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTexture::Features)
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_OPENGL_EXPORT QDebug operator<<(QDebug debug, const QOpenGLTexture *t);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLABSTRACTTEXTURE_H
diff --git a/src/opengl/qopengltexture_p.h b/src/opengl/qopengltexture_p.h
new file mode 100644
index 0000000000..1dc0801644
--- /dev/null
+++ b/src/opengl/qopengltexture_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QABSTRACTOPENGLTEXTURE_P_H
+#define QABSTRACTOPENGLTEXTURE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QT_NO_OPENGL
+
+#include <QtOpenGL/qtopenglglobal.h>
+#include "private/qobject_p.h"
+#include "qopengltexture.h"
+#include "qopengl.h"
+
+#include <cmath>
+
+namespace {
+inline double qLog2(const double x)
+{
+ return std::log(x) / std::log(2.0);
+}
+}
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QOpenGLTextureHelper;
+class QOpenGLFunctions;
+
+class QOpenGLTexturePrivate
+{
+public:
+ QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,
+ QOpenGLTexture *qq);
+ ~QOpenGLTexturePrivate();
+
+ Q_DECLARE_PUBLIC(QOpenGLTexture)
+
+ void resetFuncs(QOpenGLTextureHelper *funcs);
+ void initializeOpenGLFunctions();
+
+ bool create();
+ void destroy();
+
+ void bind();
+ void bind(uint unit, QOpenGLTexture::TextureUnitReset reset = QOpenGLTexture::DontResetTextureUnit);
+ void release();
+ void release(uint unit, QOpenGLTexture::TextureUnitReset reset = QOpenGLTexture::DontResetTextureUnit);
+ bool isBound() const;
+ bool isBound(uint unit) const;
+
+ void allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType);
+ void allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType);
+ void allocateImmutableStorage();
+ void setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options);
+ void setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
+ int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
+ const void *data, const QOpenGLPixelTransferOptions * const options);
+ void setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
+ int dataSize, const void *data,
+ const QOpenGLPixelTransferOptions * const options);
+
+
+ void setWrapMode(QOpenGLTexture::WrapMode mode);
+ void setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode);
+ QOpenGLTexture::WrapMode wrapMode(QOpenGLTexture::CoordinateDirection direction) const;
+
+ QOpenGLTexture *createTextureView(QOpenGLTexture::Target target, QOpenGLTexture::TextureFormat viewFormat,
+ int minimumMipmapLevel, int maximumMipmapLevel,
+ int minimumLayer, int maximumLayer) const;
+
+ int evaluateMipLevels() const;
+
+ inline int maximumMipLevelCount() const
+ {
+ return 1 + std::floor(qLog2(qMax(dimensions[0], qMax(dimensions[1], dimensions[2]))));
+ }
+
+ static inline int mipLevelSize(int mipLevel, int baseLevelSize)
+ {
+ return std::floor(double(qMax(1, baseLevelSize >> mipLevel)));
+ }
+
+ bool isUsingImmutableStorage() const;
+
+ QOpenGLTexture *q_ptr;
+ QOpenGLContext *context;
+ QOpenGLTexture::Target target;
+ QOpenGLTexture::BindingTarget bindingTarget;
+ GLuint textureId;
+ QOpenGLTexture::TextureFormat format;
+ QOpenGLTexture::TextureFormatClass formatClass;
+ int dimensions[3];
+ int requestedMipLevels;
+ int mipLevels;
+ int layers;
+ int faces;
+
+ int samples;
+ bool fixedSamplePositions;
+
+ int baseLevel;
+ int maxLevel;
+
+ QOpenGLTexture::SwizzleValue swizzleMask[4];
+ QOpenGLTexture::DepthStencilMode depthStencilMode;
+ QOpenGLTexture::ComparisonFunction comparisonFunction;
+ QOpenGLTexture::ComparisonMode comparisonMode;
+
+ QOpenGLTexture::Filter minFilter;
+ QOpenGLTexture::Filter magFilter;
+ float maxAnisotropy;
+ QOpenGLTexture::WrapMode wrapModes[3];
+ QVariantList borderColor;
+ float minLevelOfDetail;
+ float maxLevelOfDetail;
+ float levelOfDetailBias;
+
+ bool textureView;
+ bool autoGenerateMipMaps;
+ bool storageAllocated;
+
+ QOpenGLTextureHelper *texFuncs;
+ QOpenGLFunctions *functions;
+
+ QOpenGLTexture::Features features;
+};
+
+QT_END_NAMESPACE
+
+#undef Q_CALL_MEMBER_FUNCTION
+
+#endif // QT_NO_OPENGL
+
+#endif // QABSTRACTOPENGLTEXTURE_P_H
diff --git a/src/opengl/qopengltextureblitter.cpp b/src/opengl/qopengltextureblitter.cpp
new file mode 100644
index 0000000000..ba2eaf7754
--- /dev/null
+++ b/src/opengl/qopengltextureblitter.cpp
@@ -0,0 +1,682 @@
+/****************************************************************************
+**
+** 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 "qopengltextureblitter.h"
+
+#include <QtGui/QOpenGLBuffer>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QOpenGLVertexArrayObject>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLTextureBlitter
+ \brief The QOpenGLTextureBlitter class provides a convenient way to draw textured quads via OpenGL.
+ \since 5.8
+ \ingroup painting-3D
+ \inmodule QtOpenGL
+
+ Drawing textured quads, in order to get the contents of a texture
+ onto the screen, is a common operation when developing 2D user
+ interfaces. QOpenGLTextureBlitter provides a convenience class to
+ avoid repeating vertex data, shader sources, buffer and program
+ management and matrix calculations.
+
+ For example, a QOpenGLWidget subclass can do the following to draw
+ the contents rendered into a framebuffer at the pixel position \c{(x, y)}:
+
+ \code
+ void OpenGLWidget::initializeGL()
+ {
+ m_blitter.create();
+ m_fbo = new QOpenGLFramebufferObject(size);
+ }
+
+ void OpenGLWidget::paintGL()
+ {
+ m_fbo->bind();
+ // update offscreen content
+ m_fbo->release();
+
+ m_blitter.bind();
+ const QRect targetRect(QPoint(x, y), m_fbo->size());
+ const QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(targetRect, QRect(QPoint(0, 0), m_fbo->size()));
+ m_blitter.blit(m_fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
+ m_blitter.release();
+ }
+ \endcode
+
+ The blitter implements GLSL shaders both for GLSL 1.00 (suitable
+ for OpenGL (ES) 2.x and compatibility profiles of newer OpenGL
+ versions) and version 150 (suitable for core profile contexts with
+ OpenGL 3.2 and newer).
+ */
+
+static const char vertex_shader150[] =
+ "#version 150 core\n"
+ "in vec3 vertexCoord;"
+ "in vec2 textureCoord;"
+ "out vec2 uv;"
+ "uniform mat4 vertexTransform;"
+ "uniform mat3 textureTransform;"
+ "void main() {"
+ " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
+ " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
+ "}";
+
+static const char fragment_shader150[] =
+ "#version 150 core\n"
+ "in vec2 uv;"
+ "out vec4 fragcolor;"
+ "uniform sampler2D textureSampler;"
+ "uniform bool swizzle;"
+ "uniform float opacity;"
+ "void main() {"
+ " vec4 tmpFragColor = texture(textureSampler, uv);"
+ " tmpFragColor.a *= opacity;"
+ " fragcolor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
+ "}";
+
+static const char vertex_shader[] =
+ "attribute highp vec3 vertexCoord;"
+ "attribute highp vec2 textureCoord;"
+ "varying highp vec2 uv;"
+ "uniform highp mat4 vertexTransform;"
+ "uniform highp mat3 textureTransform;"
+ "void main() {"
+ " uv = (textureTransform * vec3(textureCoord,1.0)).xy;"
+ " gl_Position = vertexTransform * vec4(vertexCoord,1.0);"
+ "}";
+
+static const char fragment_shader[] =
+ "varying highp vec2 uv;"
+ "uniform sampler2D textureSampler;"
+ "uniform bool swizzle;"
+ "uniform highp float opacity;"
+ "void main() {"
+ " highp vec4 tmpFragColor = texture2D(textureSampler,uv);"
+ " tmpFragColor.a *= opacity;"
+ " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
+ "}";
+
+static const char fragment_shader_external_oes[] =
+ "#extension GL_OES_EGL_image_external : require\n"
+ "varying highp vec2 uv;"
+ "uniform samplerExternalOES textureSampler;\n"
+ "uniform bool swizzle;"
+ "uniform highp float opacity;"
+ "void main() {"
+ " highp vec4 tmpFragColor = texture2D(textureSampler, uv);"
+ " tmpFragColor.a *= opacity;"
+ " gl_FragColor = swizzle ? tmpFragColor.bgra : tmpFragColor;"
+ "}";
+
+static const GLfloat vertex_buffer_data[] = {
+ -1,-1, 0,
+ -1, 1, 0,
+ 1,-1, 0,
+ -1, 1, 0,
+ 1,-1, 0,
+ 1, 1, 0
+};
+
+static const GLfloat texture_buffer_data[] = {
+ 0, 0,
+ 0, 1,
+ 1, 0,
+ 0, 1,
+ 1, 0,
+ 1, 1
+};
+
+class TextureBinder
+{
+public:
+ TextureBinder(GLenum target, GLuint textureId) : m_target(target)
+ {
+ QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, textureId);
+ }
+ ~TextureBinder()
+ {
+ QOpenGLContext::currentContext()->functions()->glBindTexture(m_target, 0);
+ }
+
+private:
+ GLenum m_target;
+};
+
+class QOpenGLTextureBlitterPrivate
+{
+public:
+ enum TextureMatrixUniform {
+ User,
+ Identity,
+ IdentityFlipped
+ };
+
+ enum ProgramIndex {
+ TEXTURE_2D,
+ TEXTURE_EXTERNAL_OES
+ };
+
+ QOpenGLTextureBlitterPrivate() :
+ swizzle(false),
+ opacity(1.0f),
+ vao(new QOpenGLVertexArrayObject),
+ currentTarget(TEXTURE_2D)
+ { }
+
+ bool buildProgram(ProgramIndex idx, const char *vs, const char *fs);
+
+ void blit(GLuint texture, const QMatrix4x4 &vertexTransform, const QMatrix3x3 &textureTransform);
+ void blit(GLuint texture, const QMatrix4x4 &vertexTransform, QOpenGLTextureBlitter::Origin origin);
+
+ void prepareProgram(const QMatrix4x4 &vertexTransform);
+
+ QOpenGLBuffer vertexBuffer;
+ QOpenGLBuffer textureBuffer;
+ struct Program {
+ Program() :
+ vertexCoordAttribPos(0),
+ vertexTransformUniformPos(0),
+ textureCoordAttribPos(0),
+ textureTransformUniformPos(0),
+ swizzleUniformPos(0),
+ opacityUniformPos(0),
+ swizzle(false),
+ opacity(0.0f),
+ textureMatrixUniformState(User)
+ { }
+ QScopedPointer<QOpenGLShaderProgram> glProgram;
+ GLuint vertexCoordAttribPos;
+ GLuint vertexTransformUniformPos;
+ GLuint textureCoordAttribPos;
+ GLuint textureTransformUniformPos;
+ GLuint swizzleUniformPos;
+ GLuint opacityUniformPos;
+ bool swizzle;
+ float opacity;
+ TextureMatrixUniform textureMatrixUniformState;
+ } programs[2];
+ bool swizzle;
+ float opacity;
+ QScopedPointer<QOpenGLVertexArrayObject> vao;
+ GLenum currentTarget;
+};
+
+static inline QOpenGLTextureBlitterPrivate::ProgramIndex targetToProgramIndex(GLenum target)
+{
+ switch (target) {
+ case GL_TEXTURE_2D:
+ return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
+ case GL_TEXTURE_EXTERNAL_OES:
+ return QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES;
+ default:
+ qWarning("Unsupported texture target 0x%x", target);
+ return QOpenGLTextureBlitterPrivate::TEXTURE_2D;
+ }
+}
+
+void QOpenGLTextureBlitterPrivate::prepareProgram(const QMatrix4x4 &vertexTransform)
+{
+ Program *program = &programs[targetToProgramIndex(currentTarget)];
+
+ vertexBuffer.bind();
+ program->glProgram->setAttributeBuffer(program->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
+ program->glProgram->enableAttributeArray(program->vertexCoordAttribPos);
+ vertexBuffer.release();
+
+ program->glProgram->setUniformValue(program->vertexTransformUniformPos, vertexTransform);
+
+ textureBuffer.bind();
+ program->glProgram->setAttributeBuffer(program->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
+ program->glProgram->enableAttributeArray(program->textureCoordAttribPos);
+ textureBuffer.release();
+
+ if (swizzle != program->swizzle) {
+ program->glProgram->setUniformValue(program->swizzleUniformPos, swizzle);
+ program->swizzle = swizzle;
+ }
+
+ if (opacity != program->opacity) {
+ program->glProgram->setUniformValue(program->opacityUniformPos, opacity);
+ program->opacity = opacity;
+ }
+}
+
+void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
+ const QMatrix4x4 &vertexTransform,
+ const QMatrix3x3 &textureTransform)
+{
+ TextureBinder binder(currentTarget, texture);
+ prepareProgram(vertexTransform);
+
+ Program *program = &programs[targetToProgramIndex(currentTarget)];
+ program->glProgram->setUniformValue(program->textureTransformUniformPos, textureTransform);
+ program->textureMatrixUniformState = User;
+
+ QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+void QOpenGLTextureBlitterPrivate::blit(GLuint texture,
+ const QMatrix4x4 &vertexTransform,
+ QOpenGLTextureBlitter::Origin origin)
+{
+ TextureBinder binder(currentTarget, texture);
+ prepareProgram(vertexTransform);
+
+ Program *program = &programs[targetToProgramIndex(currentTarget)];
+ if (origin == QOpenGLTextureBlitter::OriginTopLeft) {
+ if (program->textureMatrixUniformState != IdentityFlipped) {
+ QMatrix3x3 flipped;
+ flipped(1,1) = -1;
+ flipped(1,2) = 1;
+ program->glProgram->setUniformValue(program->textureTransformUniformPos, flipped);
+ program->textureMatrixUniformState = IdentityFlipped;
+ }
+ } else if (program->textureMatrixUniformState != Identity) {
+ program->glProgram->setUniformValue(program->textureTransformUniformPos, QMatrix3x3());
+ program->textureMatrixUniformState = Identity;
+ }
+
+ QOpenGLContext::currentContext()->functions()->glDrawArrays(GL_TRIANGLES, 0, 6);
+}
+
+bool QOpenGLTextureBlitterPrivate::buildProgram(ProgramIndex idx, const char *vs, const char *fs)
+{
+ Program *p = &programs[idx];
+
+ p->glProgram.reset(new QOpenGLShaderProgram);
+
+ p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, vs);
+ p->glProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, fs);
+ p->glProgram->link();
+ if (!p->glProgram->isLinked()) {
+ qWarning() << "Could not link shader program:\n" << p->glProgram->log();
+ return false;
+ }
+
+ p->glProgram->bind();
+
+ p->vertexCoordAttribPos = p->glProgram->attributeLocation("vertexCoord");
+ p->vertexTransformUniformPos = p->glProgram->uniformLocation("vertexTransform");
+ p->textureCoordAttribPos = p->glProgram->attributeLocation("textureCoord");
+ p->textureTransformUniformPos = p->glProgram->uniformLocation("textureTransform");
+ p->swizzleUniformPos = p->glProgram->uniformLocation("swizzle");
+ p->opacityUniformPos = p->glProgram->uniformLocation("opacity");
+
+ p->glProgram->setUniformValue(p->swizzleUniformPos, false);
+
+ // minmize state left set after a create()
+ p->glProgram->release();
+
+ return true;
+}
+
+/*!
+ Constructs a new QOpenGLTextureBlitter instance.
+
+ \note no graphics resources are initialized in the
+ constructor. This makes it safe to place plain
+ QOpenGLTextureBlitter members into classes because the actual
+ initialization that depends on the OpenGL context happens only in
+ create().
+ */
+QOpenGLTextureBlitter::QOpenGLTextureBlitter()
+ : d_ptr(new QOpenGLTextureBlitterPrivate)
+{
+}
+
+/*!
+ Destructs the instance.
+
+ \note When the OpenGL context - or a context sharing resources
+ with it - that was current when calling create() is not current,
+ graphics resources will not be released. Therefore, it is
+ recommended to call destroy() manually instead of relying on the
+ destructor to perform OpenGL resource cleanup.
+ */
+QOpenGLTextureBlitter::~QOpenGLTextureBlitter()
+{
+ destroy();
+}
+
+/*!
+ Initializes the graphics resources used by the blitter.
+
+ \return \c true if successful, \c false if there was a
+ failure. Failures can occur when there is no OpenGL context
+ current on the current thread, or when shader compilation fails
+ for some reason.
+
+ \sa isCreated(), destroy()
+ */
+bool QOpenGLTextureBlitter::create()
+{
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext)
+ return false;
+
+ Q_D(QOpenGLTextureBlitter);
+
+ if (d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram)
+ return true;
+
+ QSurfaceFormat format = currentContext->format();
+ if (format.profile() == QSurfaceFormat::CoreProfile && format.version() >= qMakePair(3,2)) {
+ if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader150, fragment_shader150))
+ return false;
+ } else {
+ if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_2D, vertex_shader, fragment_shader))
+ return false;
+ if (supportsExternalOESTarget())
+ if (!d->buildProgram(QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES, vertex_shader, fragment_shader_external_oes))
+ return false;
+ }
+
+ // Create and bind the VAO, if supported.
+ QOpenGLVertexArrayObject::Binder vaoBinder(d->vao.data());
+
+ d->vertexBuffer.create();
+ d->vertexBuffer.bind();
+ d->vertexBuffer.allocate(vertex_buffer_data, sizeof(vertex_buffer_data));
+ d->vertexBuffer.release();
+
+ d->textureBuffer.create();
+ d->textureBuffer.bind();
+ d->textureBuffer.allocate(texture_buffer_data, sizeof(texture_buffer_data));
+ d->textureBuffer.release();
+
+ return true;
+}
+
+/*!
+ \return \c true if create() was called and succeeded. \c false otherwise.
+
+ \sa create(), destroy()
+ */
+bool QOpenGLTextureBlitter::isCreated() const
+{
+ Q_D(const QOpenGLTextureBlitter);
+ return d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram;
+}
+
+/*!
+ Frees all graphics resources held by the blitter. Assumes that
+ the OpenGL context, or another context sharing resources with it,
+ that was current on the thread when invoking create() is current.
+
+ The function has no effect when the blitter is not in created state.
+
+ \sa create()
+ */
+void QOpenGLTextureBlitter::destroy()
+{
+ if (!isCreated())
+ return;
+ Q_D(QOpenGLTextureBlitter);
+ d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_2D].glProgram.reset();
+ d->programs[QOpenGLTextureBlitterPrivate::TEXTURE_EXTERNAL_OES].glProgram.reset();
+ d->vertexBuffer.destroy();
+ d->textureBuffer.destroy();
+ d->vao.reset();
+}
+
+/*!
+ \return \c true when bind() accepts \c GL_TEXTURE_EXTERNAL_OES as
+ its target argument.
+
+ \sa bind(), blit()
+ */
+bool QOpenGLTextureBlitter::supportsExternalOESTarget() const
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ return ctx && ctx->isOpenGLES() && ctx->hasExtension("GL_OES_EGL_image_external");
+}
+
+/*!
+ Binds the graphics resources used by the blitter. This must be
+ called before calling blit(). Code modifying the OpenGL state
+ should be avoided between the call to bind() and blit() because
+ otherwise conflicts may arise.
+
+ \a target is the texture target for the source texture and must be
+ either \c GL_TEXTURE_2D or \c GL_OES_EGL_image_external.
+
+ \sa release(), blit()
+ */
+void QOpenGLTextureBlitter::bind(GLenum target)
+{
+ Q_D(QOpenGLTextureBlitter);
+
+ if (d->vao->isCreated())
+ d->vao->bind();
+
+ d->currentTarget = target;
+ QOpenGLTextureBlitterPrivate::Program *p = &d->programs[targetToProgramIndex(target)];
+ p->glProgram->bind();
+
+ d->vertexBuffer.bind();
+ p->glProgram->setAttributeBuffer(p->vertexCoordAttribPos, GL_FLOAT, 0, 3, 0);
+ p->glProgram->enableAttributeArray(p->vertexCoordAttribPos);
+ d->vertexBuffer.release();
+
+ d->textureBuffer.bind();
+ p->glProgram->setAttributeBuffer(p->textureCoordAttribPos, GL_FLOAT, 0, 2, 0);
+ p->glProgram->enableAttributeArray(p->textureCoordAttribPos);
+ d->textureBuffer.release();
+}
+
+/*!
+ Unbinds the graphics resources used by the blitter.
+
+ \sa bind()
+ */
+void QOpenGLTextureBlitter::release()
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->programs[targetToProgramIndex(d->currentTarget)].glProgram->release();
+ if (d->vao->isCreated())
+ d->vao->release();
+}
+
+/*!
+ Sets whether swizzling is enabled for the red and blue color channels to
+ \a swizzle. An BGRA to RGBA conversion (occurring in the shader on
+ the GPU, instead of a slow CPU-side transformation) can be useful
+ when the source texture contains data from a QImage with a format
+ like QImage::Format_ARGB32 which maps to BGRA on little endian
+ systems.
+
+ By default the red-blue swizzle is disabled since this is what a
+ texture attached to an framebuffer object or a texture based on a
+ byte ordered QImage format (like QImage::Format_RGBA8888) needs.
+ */
+void QOpenGLTextureBlitter::setRedBlueSwizzle(bool swizzle)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->swizzle = swizzle;
+}
+
+/*!
+ Changes the opacity to \a opacity. The default opacity is 1.0.
+
+ \note the blitter does not alter the blend state. It is up to the
+ caller of blit() to ensure the correct blend settings are active.
+
+ */
+void QOpenGLTextureBlitter::setOpacity(float opacity)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->opacity = opacity;
+}
+
+/*!
+ \enum QOpenGLTextureBlitter::Origin
+
+ \value OriginBottomLeft Indicates that the data in the texture
+ follows the OpenGL convention of coordinate systems, meaning Y is
+ running from bottom to top.
+
+ \value OriginTopLeft Indicates that the data in the texture has Y
+ running from top to bottom, which is typical with regular,
+ unflipped image data.
+
+ \sa blit()
+ */
+
+/*!
+ Performs the blit with the source texture \a texture.
+
+ \a targetTransform specifies the transformation applied. This is
+ usually generated by the targetTransform() helper function.
+
+ \a sourceOrigin specifies if the image data needs flipping. When
+ \a texture corresponds to a texture attached to an FBO pass
+ OriginBottomLeft. On the other hand, when \a texture is based on
+ unflipped image data, pass OriginTopLeft. This is more efficient
+ than using QImage::mirrored().
+
+ \sa targetTransform(), Origin, bind()
+ */
+void QOpenGLTextureBlitter::blit(GLuint texture,
+ const QMatrix4x4 &targetTransform,
+ Origin sourceOrigin)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->blit(texture,targetTransform, sourceOrigin);
+}
+
+/*!
+ Performs the blit with the source texture \a texture.
+
+ \a targetTransform specifies the transformation applied. This is
+ usually generated by the targetTransform() helper function.
+
+ \a sourceTransform specifies the transformation applied to the
+ source. This allows using only a sub-rect of the source
+ texture. This is usually generated by the sourceTransform() helper
+ function.
+
+ \sa sourceTransform(), targetTransform(), Origin, bind()
+ */
+void QOpenGLTextureBlitter::blit(GLuint texture,
+ const QMatrix4x4 &targetTransform,
+ const QMatrix3x3 &sourceTransform)
+{
+ Q_D(QOpenGLTextureBlitter);
+ d->blit(texture, targetTransform, sourceTransform);
+}
+
+/*!
+ Calculates a target transform suitable for blit().
+
+ \a target is the target rectangle in pixels. \a viewport describes
+ the source dimensions and will in most cases be set to (0, 0,
+ image width, image height).
+
+ For unscaled output the size of \a target and \a viewport should
+ match.
+
+ \sa blit()
+ */
+QMatrix4x4 QOpenGLTextureBlitter::targetTransform(const QRectF &target,
+ const QRect &viewport)
+{
+ qreal x_scale = target.width() / viewport.width();
+ qreal y_scale = target.height() / viewport.height();
+
+ const QPointF relative_to_viewport = target.topLeft() - viewport.topLeft();
+ qreal x_translate = x_scale - 1 + ((relative_to_viewport.x() / viewport.width()) * 2);
+ qreal y_translate = -y_scale + 1 - ((relative_to_viewport.y() / viewport.height()) * 2);
+
+ QMatrix4x4 matrix;
+ matrix(0,3) = x_translate;
+ matrix(1,3) = y_translate;
+
+ matrix(0,0) = x_scale;
+ matrix(1,1) = y_scale;
+
+ return matrix;
+}
+
+/*!
+ Calculates a 3x3 matrix suitable as the input to blit(). This is
+ used when only a part of the texture is to be used in the blit.
+
+ \a subTexture is the desired source rectangle in pixels, \a
+ textureSize is the full width and height of the texture data. \a
+ origin specifies the orientation of the image data when it comes
+ to the Y axis.
+
+ \sa blit(), Origin
+ */
+QMatrix3x3 QOpenGLTextureBlitter::sourceTransform(const QRectF &subTexture,
+ const QSize &textureSize,
+ Origin origin)
+{
+ qreal x_scale = subTexture.width() / textureSize.width();
+ qreal y_scale = subTexture.height() / textureSize.height();
+
+ const QPointF topLeft = subTexture.topLeft();
+ qreal x_translate = topLeft.x() / textureSize.width();
+ qreal y_translate = topLeft.y() / textureSize.height();
+
+ if (origin == OriginTopLeft) {
+ y_scale = -y_scale;
+ y_translate = 1 - y_translate;
+ }
+
+ QMatrix3x3 matrix;
+ matrix(0,2) = x_translate;
+ matrix(1,2) = y_translate;
+
+ matrix(0,0) = x_scale;
+ matrix(1,1) = y_scale;
+
+ return matrix;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qglcolormap.h b/src/opengl/qopengltextureblitter.h
index b59b56e040..1818576085 100644
--- a/src/opengl/qglcolormap.h
+++ b/src/opengl/qopengltextureblitter.h
@@ -37,63 +37,54 @@
**
****************************************************************************/
-#ifndef QGLCOLORMAP_H
-#define QGLCOLORMAP_H
+#ifndef QOPENGLTEXTUREBLITTER_H
+#define QOPENGLTEXTUREBLITTER_H
-#include <QtGui/qcolor.h>
-#include <QtCore/qvector.h>
#include <QtOpenGL/qtopenglglobal.h>
+#include <QtGui/qopengl.h>
+#include <QtGui/QMatrix3x3>
+#include <QtGui/QMatrix4x4>
+
QT_BEGIN_NAMESPACE
+class QOpenGLTextureBlitterPrivate;
-class Q_OPENGL_EXPORT QGLColormap
+class Q_OPENGL_EXPORT QOpenGLTextureBlitter
{
public:
- QGLColormap();
- QGLColormap(const QGLColormap &);
- ~QGLColormap();
+ QOpenGLTextureBlitter();
+ ~QOpenGLTextureBlitter();
- QGLColormap &operator=(const QGLColormap &);
+ enum Origin {
+ OriginBottomLeft,
+ OriginTopLeft
+ };
- bool isEmpty() const;
- int size() const;
- void detach();
+ bool create();
+ bool isCreated() const;
+ void destroy();
- void setEntries(int count, const QRgb * colors, int base = 0);
- void setEntry(int idx, QRgb color);
- void setEntry(int idx, const QColor & color);
- QRgb entryRgb(int idx) const;
- QColor entryColor(int idx) const;
- int find(QRgb color) const;
- int findNearest(QRgb color) const;
+ bool supportsExternalOESTarget() const;
-protected:
- Qt::HANDLE handle() { return d ? d->cmapHandle : nullptr; }
- void setHandle(Qt::HANDLE ahandle) { d->cmapHandle = ahandle; }
+ void bind(GLenum target = GL_TEXTURE_2D);
+ void release();
-private:
- struct QGLColormapData {
- QBasicAtomicInt ref;
- QVector<QRgb> *cells;
- Qt::HANDLE cmapHandle;
- };
+ void setRedBlueSwizzle(bool swizzle);
+ void setOpacity(float opacity);
- QGLColormapData *d;
- static struct QGLColormapData shared_null;
- static void cleanup(QGLColormapData *x);
- void detach_helper();
+ void blit(GLuint texture, const QMatrix4x4 &targetTransform, Origin sourceOrigin);
+ void blit(GLuint texture, const QMatrix4x4 &targetTransform, const QMatrix3x3 &sourceTransform);
- friend class QGLWidget;
- friend class QGLWidgetPrivate;
-};
+ static QMatrix4x4 targetTransform(const QRectF &target, const QRect &viewport);
+ static QMatrix3x3 sourceTransform(const QRectF &subTexture, const QSize &textureSize, Origin origin);
-inline void QGLColormap::detach()
-{
- if (d->ref.loadRelaxed() != 1)
- detach_helper();
-}
+private:
+ Q_DISABLE_COPY(QOpenGLTextureBlitter)
+ Q_DECLARE_PRIVATE(QOpenGLTextureBlitter)
+ QScopedPointer<QOpenGLTextureBlitterPrivate> d_ptr;
+};
QT_END_NAMESPACE
-#endif // QGLCOLORMAP_H
+#endif //QOPENGLTEXTUREBLITTER_H
diff --git a/src/opengl/qopengltexturecache.cpp b/src/opengl/qopengltexturecache.cpp
new file mode 100644
index 0000000000..5256c429e0
--- /dev/null
+++ b/src/opengl/qopengltexturecache.cpp
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** 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 "qopengltexturecache_p.h"
+#include <private/qopengltextureuploader_p.h>
+#include <qmath.h>
+#include <qopenglfunctions.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
+#include <qpa/qplatformpixmap.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLTextureCacheWrapper
+{
+public:
+ QOpenGLTextureCacheWrapper()
+ {
+ QImagePixmapCleanupHooks::instance()->addPlatformPixmapModificationHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->addPlatformPixmapDestructionHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->addImageHook(cleanupTexturesForCacheKey);
+ }
+
+ ~QOpenGLTextureCacheWrapper()
+ {
+ QImagePixmapCleanupHooks::instance()->removePlatformPixmapModificationHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->removePlatformPixmapDestructionHook(cleanupTexturesForPixmapData);
+ QImagePixmapCleanupHooks::instance()->removeImageHook(cleanupTexturesForCacheKey);
+ }
+
+ QOpenGLTextureCache *cacheForContext(QOpenGLContext *context) {
+ QMutexLocker lock(&m_mutex);
+ return m_resource.value<QOpenGLTextureCache>(context);
+ }
+
+ static void cleanupTexturesForCacheKey(qint64 key);
+ static void cleanupTexturesForPixmapData(QPlatformPixmap *pmd);
+
+private:
+ QOpenGLMultiGroupSharedResource m_resource;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QOpenGLTextureCacheWrapper, qt_texture_caches)
+
+QOpenGLTextureCache *QOpenGLTextureCache::cacheForContext(QOpenGLContext *context)
+{
+ return qt_texture_caches()->cacheForContext(context);
+}
+
+void QOpenGLTextureCacheWrapper::cleanupTexturesForCacheKey(qint64 key)
+{
+ QList<QOpenGLSharedResource *> resources = qt_texture_caches()->m_resource.resources();
+ for (QList<QOpenGLSharedResource *>::iterator it = resources.begin(); it != resources.end(); ++it)
+ static_cast<QOpenGLTextureCache *>(*it)->invalidate(key);
+}
+
+void QOpenGLTextureCacheWrapper::cleanupTexturesForPixmapData(QPlatformPixmap *pmd)
+{
+ cleanupTexturesForCacheKey(pmd->cacheKey());
+}
+
+QOpenGLTextureCache::QOpenGLTextureCache(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , m_cache(256 * 1024) // 256 MB cache
+{
+}
+
+QOpenGLTextureCache::~QOpenGLTextureCache()
+{
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QPixmap &pixmap, QOpenGLTextureUploader::BindOptions options)
+{
+ if (pixmap.isNull())
+ return 0;
+ QMutexLocker locker(&m_mutex);
+ qint64 key = pixmap.cacheKey();
+
+ // A QPainter is active on the image - take the safe route and replace the texture.
+ if (!pixmap.paintingActive()) {
+ QOpenGLCachedTexture *entry = m_cache.object(key);
+ if (entry && entry->options() == options) {
+ context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());
+ return entry->id();
+ }
+ }
+
+ GLuint id = bindTexture(context, key, pixmap.toImage(), options);
+ if (id > 0)
+ QImagePixmapCleanupHooks::enableCleanupHooks(pixmap);
+
+ return id;
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, const QImage &image, QOpenGLTextureUploader::BindOptions options)
+{
+ if (image.isNull())
+ return 0;
+ QMutexLocker locker(&m_mutex);
+ qint64 key = image.cacheKey();
+
+ // A QPainter is active on the image - take the safe route and replace the texture.
+ if (!image.paintingActive()) {
+ QOpenGLCachedTexture *entry = m_cache.object(key);
+ if (entry && entry->options() == options) {
+ context->functions()->glBindTexture(GL_TEXTURE_2D, entry->id());
+ return entry->id();
+ }
+ }
+
+ QImage img = image;
+ if (!context->functions()->hasOpenGLFeature(QOpenGLFunctions::NPOTTextures))
+ options |= QOpenGLTextureUploader::PowerOfTwoBindOption;
+
+ GLuint id = bindTexture(context, key, img, options);
+ if (id > 0)
+ QImagePixmapCleanupHooks::enableCleanupHooks(image);
+
+ return id;
+}
+
+GLuint QOpenGLTextureCache::bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options)
+{
+ GLuint id;
+ QOpenGLFunctions *funcs = context->functions();
+ funcs->glGenTextures(1, &id);
+ funcs->glBindTexture(GL_TEXTURE_2D, id);
+
+ int cost = QOpenGLTextureUploader::textureImage(GL_TEXTURE_2D, image, options);
+
+ m_cache.insert(key, new QOpenGLCachedTexture(id, options, context), cost / 1024);
+
+ return id;
+}
+
+void QOpenGLTextureCache::invalidate(qint64 key)
+{
+ QMutexLocker locker(&m_mutex);
+ m_cache.remove(key);
+}
+
+void QOpenGLTextureCache::invalidateResource()
+{
+ m_cache.clear();
+}
+
+void QOpenGLTextureCache::freeResource(QOpenGLContext *)
+{
+ Q_ASSERT(false); // the texture cache lives until the context group disappears
+}
+
+static void freeTexture(QOpenGLFunctions *funcs, GLuint id)
+{
+ funcs->glDeleteTextures(1, &id);
+}
+
+QOpenGLCachedTexture::QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context) : m_options(options)
+{
+ m_resource = new QOpenGLSharedResourceGuard(context, id, freeTexture);
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopengltexturecache_p.h b/src/opengl/qopengltexturecache_p.h
new file mode 100644
index 0000000000..14e03ebea1
--- /dev/null
+++ b/src/opengl/qopengltexturecache_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** 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 QOPENGLTEXTURECACHE_P_H
+#define QOPENGLTEXTURECACHE_P_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+#include <QHash>
+#include <QObject>
+#include <QCache>
+#include <private/qopenglcontext_p.h>
+#include <private/qopengltextureuploader_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLCachedTexture;
+
+class Q_OPENGL_EXPORT QOpenGLTextureCache : public QOpenGLSharedResource
+{
+public:
+ static QOpenGLTextureCache *cacheForContext(QOpenGLContext *context);
+
+ QOpenGLTextureCache(QOpenGLContext *);
+ ~QOpenGLTextureCache();
+
+ GLuint bindTexture(QOpenGLContext *context, const QPixmap &pixmap,
+ QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption);
+ GLuint bindTexture(QOpenGLContext *context, const QImage &image,
+ QOpenGLTextureUploader::BindOptions options = QOpenGLTextureUploader::PremultipliedAlphaBindOption);
+
+ void invalidate(qint64 key);
+
+ void invalidateResource() override;
+ void freeResource(QOpenGLContext *ctx) override;
+
+private:
+ GLuint bindTexture(QOpenGLContext *context, qint64 key, const QImage &image, QOpenGLTextureUploader::BindOptions options);
+
+ QMutex m_mutex;
+ QCache<quint64, QOpenGLCachedTexture> m_cache;
+};
+
+class QOpenGLCachedTexture
+{
+public:
+ QOpenGLCachedTexture(GLuint id, QOpenGLTextureUploader::BindOptions options, QOpenGLContext *context);
+ ~QOpenGLCachedTexture() { m_resource->free(); }
+
+ GLuint id() const { return m_resource->id(); }
+ QOpenGLTextureUploader::BindOptions options() const { return m_options; }
+
+private:
+ QOpenGLSharedResourceGuard *m_resource;
+ QOpenGLTextureUploader::BindOptions m_options;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/opengl/qopengltextureglyphcache.cpp b/src/opengl/qopengltextureglyphcache.cpp
new file mode 100644
index 0000000000..66fd3a7507
--- /dev/null
+++ b/src/opengl/qopengltextureglyphcache.cpp
@@ -0,0 +1,485 @@
+/****************************************************************************
+**
+** 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 "qopengltextureglyphcache_p.h"
+#include <private/qopenglpaintengine_p.h>
+#include "private/qopenglengineshadersource_p.h"
+#include <private/qopenglextensions_p.h>
+#include <qrgb.h>
+#include <private/qdrawhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+
+static int next_qopengltextureglyphcache_serial_number()
+{
+ static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+ return 1 + serial.fetchAndAddRelaxed(1);
+}
+
+QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix, const QColor &color)
+ : QImageTextureGlyphCache(format, matrix, color)
+ , m_textureResource(nullptr)
+ , pex(nullptr)
+ , m_blitProgram(nullptr)
+ , m_filterMode(Nearest)
+ , m_serialNumber(next_qopengltextureglyphcache_serial_number())
+ , m_buffer(QOpenGLBuffer::VertexBuffer)
+{
+#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
+ qDebug(" -> QOpenGLTextureGlyphCache() %p for context %p.", this, QOpenGLContext::currentContext());
+#endif
+ m_vertexCoordinateArray[0] = -1.0f;
+ m_vertexCoordinateArray[1] = -1.0f;
+ m_vertexCoordinateArray[2] = 1.0f;
+ m_vertexCoordinateArray[3] = -1.0f;
+ m_vertexCoordinateArray[4] = 1.0f;
+ m_vertexCoordinateArray[5] = 1.0f;
+ m_vertexCoordinateArray[6] = -1.0f;
+ m_vertexCoordinateArray[7] = 1.0f;
+
+ m_textureCoordinateArray[0] = 0.0f;
+ m_textureCoordinateArray[1] = 0.0f;
+ m_textureCoordinateArray[2] = 1.0f;
+ m_textureCoordinateArray[3] = 0.0f;
+ m_textureCoordinateArray[4] = 1.0f;
+ m_textureCoordinateArray[5] = 1.0f;
+ m_textureCoordinateArray[6] = 0.0f;
+ m_textureCoordinateArray[7] = 1.0f;
+}
+
+QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache()
+{
+#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
+ qDebug(" -> ~QOpenGLTextureGlyphCache() %p.", this);
+#endif
+ clear();
+}
+
+#if !defined(QT_OPENGL_ES_2)
+static inline bool isCoreProfile()
+{
+ return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile;
+}
+#endif
+
+void QOpenGLTextureGlyphCache::createTextureData(int width, int height)
+{
+ QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ if (ctx == nullptr) {
+ qWarning("QOpenGLTextureGlyphCache::createTextureData: Called with no context");
+ return;
+ }
+
+ // create in QImageTextureGlyphCache baseclass is meant to be called
+ // only to create the initial image and does not preserve the content,
+ // so we don't call when this function is called from resize.
+ if (ctx->d_func()->workaround_brokenFBOReadBack && image().isNull())
+ QImageTextureGlyphCache::createTextureData(width, height);
+
+ // Make the lower glyph texture size 16 x 16.
+ if (width < 16)
+ width = 16;
+ if (height < 16)
+ height = 16;
+
+ if (m_textureResource && !m_textureResource->m_texture) {
+ delete m_textureResource;
+ m_textureResource = nullptr;
+ }
+
+ if (!m_textureResource)
+ m_textureResource = new QOpenGLGlyphTexture(ctx);
+
+ QOpenGLFunctions *funcs = ctx->functions();
+ funcs->glGenTextures(1, &m_textureResource->m_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+
+ m_textureResource->m_width = width;
+ m_textureResource->m_height = height;
+
+ if (m_format == QFontEngine::Format_A32 || m_format == QFontEngine::Format_ARGB) {
+ QVarLengthArray<uchar> data(width * height * 4);
+ for (int i = 0; i < data.size(); ++i)
+ data[i] = 0;
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
+ } else {
+ QVarLengthArray<uchar> data(width * height);
+ for (int i = 0; i < data.size(); ++i)
+ data[i] = 0;
+#if !defined(QT_OPENGL_ES_2)
+ const GLint internalFormat = isCoreProfile() ? GL_R8 : GL_ALPHA;
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLint internalFormat = GL_ALPHA;
+ const GLenum format = GL_ALPHA;
+#endif
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, &data[0]);
+ }
+
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_filterMode = Nearest;
+
+ if (!m_buffer.isCreated()) {
+ m_buffer.create();
+ m_buffer.bind();
+ static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)];
+ memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray));
+ memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)),
+ m_textureCoordinateArray,
+ sizeof(m_textureCoordinateArray));
+ m_buffer.allocate(buf, sizeof(buf));
+ m_buffer.release();
+ }
+
+ if (!m_vao.isCreated())
+ m_vao.create();
+}
+
+void QOpenGLTextureGlyphCache::setupVertexAttribs()
+{
+ m_buffer.bind();
+ m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), GL_FLOAT, 0, 2);
+ m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), GL_FLOAT, sizeof(m_vertexCoordinateArray), 2);
+ m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ m_buffer.release();
+}
+
+static void load_glyph_image_to_texture(QOpenGLContext *ctx,
+ QImage &img,
+ GLuint texture,
+ int tx, int ty)
+{
+ QOpenGLFunctions *funcs = ctx->functions();
+
+ const int imgWidth = img.width();
+ const int imgHeight = img.height();
+
+ if (img.format() == QImage::Format_Mono) {
+ img = img.convertToFormat(QImage::Format_Grayscale8);
+ } else if (img.depth() == 32) {
+ if (img.format() == QImage::Format_RGB32
+ // We need to make the alpha component equal to the average of the RGB values.
+ // This is needed when drawing sub-pixel antialiased text on translucent targets.
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ || img.format() == QImage::Format_ARGB32_Premultiplied
+#else
+ || (img.format() == QImage::Format_ARGB32_Premultiplied
+ && ctx->isOpenGLES())
+#endif
+ ) {
+ for (int y = 0; y < imgHeight; ++y) {
+ QRgb *src = (QRgb *) img.scanLine(y);
+ for (int x = 0; x < imgWidth; ++x) {
+ int r = qRed(src[x]);
+ int g = qGreen(src[x]);
+ int b = qBlue(src[x]);
+ int avg;
+ if (img.format() == QImage::Format_RGB32)
+ avg = (r + g + b + 1) / 3; // "+1" for rounding.
+ else // Format_ARGB_Premultiplied
+ avg = qAlpha(src[x]);
+
+ src[x] = qRgba(r, g, b, avg);
+ // swizzle the bits to accommodate for the GL_RGBA upload.
+#if Q_BYTE_ORDER != Q_BIG_ENDIAN
+ if (ctx->isOpenGLES())
+#endif
+ src[x] = ARGB2RGBA(src[x]);
+ }
+ }
+ }
+ }
+
+ funcs->glBindTexture(GL_TEXTURE_2D, texture);
+ if (img.depth() == 32) {
+#ifdef QT_OPENGL_ES_2
+ GLenum fmt = GL_RGBA;
+#else
+ GLenum fmt = ctx->isOpenGLES() ? GL_RGBA : GL_BGRA;
+#endif // QT_OPENGL_ES_2
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ fmt = GL_RGBA;
+#endif
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, fmt, GL_UNSIGNED_BYTE, img.constBits());
+ } else {
+ // The scanlines in image are 32-bit aligned, even for mono or 8-bit formats. This
+ // is good because it matches the default of 4 bytes for GL_UNPACK_ALIGNMENT.
+#if !defined(QT_OPENGL_ES_2)
+ const GLenum format = isCoreProfile() ? GL_RED : GL_ALPHA;
+#else
+ const GLenum format = GL_ALPHA;
+#endif
+ funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, imgWidth, imgHeight, format, GL_UNSIGNED_BYTE, img.constBits());
+ }
+}
+
+static void load_glyph_image_region_to_texture(QOpenGLContext *ctx,
+ const QImage &srcImg,
+ int x, int y,
+ int w, int h,
+ GLuint texture,
+ int tx, int ty)
+{
+ Q_ASSERT(x + w <= srcImg.width() && y + h <= srcImg.height());
+
+ QImage img;
+ if (x != 0 || y != 0 || w != srcImg.width() || h != srcImg.height())
+ img = srcImg.copy(x, y, w, h);
+ else
+ img = srcImg;
+
+ load_glyph_image_to_texture(ctx, img, texture, tx, ty);
+}
+
+void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx == nullptr) {
+ qWarning("QOpenGLTextureGlyphCache::resizeTextureData: Called with no context");
+ return;
+ }
+
+ QOpenGLFunctions *funcs = ctx->functions();
+ GLint oldFbo;
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldFbo);
+
+ int oldWidth = m_textureResource->m_width;
+ int oldHeight = m_textureResource->m_height;
+
+ // Make the lower glyph texture size 16 x 16.
+ if (width < 16)
+ width = 16;
+ if (height < 16)
+ height = 16;
+
+ GLuint oldTexture = m_textureResource->m_texture;
+ createTextureData(width, height);
+
+ if (ctx->d_func()->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::resizeTextureData(width, height);
+ load_glyph_image_region_to_texture(ctx, image(), 0, 0, qMin(oldWidth, width), qMin(oldHeight, height),
+ m_textureResource->m_texture, 0, 0);
+ return;
+ }
+
+ // ### the QTextureGlyphCache API needs to be reworked to allow
+ // ### resizeTextureData to fail
+
+ funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo);
+
+ GLuint tmp_texture;
+ funcs->glGenTextures(1, &tmp_texture);
+ funcs->glBindTexture(GL_TEXTURE_2D, tmp_texture);
+ funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ m_filterMode = Nearest;
+ funcs->glBindTexture(GL_TEXTURE_2D, 0);
+ funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, tmp_texture, 0);
+
+ funcs->glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ funcs->glBindTexture(GL_TEXTURE_2D, oldTexture);
+
+ if (pex != nullptr)
+ pex->transferMode(BrushDrawingMode);
+
+ funcs->glDisable(GL_STENCIL_TEST);
+ funcs->glDisable(GL_DEPTH_TEST);
+ funcs->glDisable(GL_SCISSOR_TEST);
+ funcs->glDisable(GL_BLEND);
+
+ funcs->glViewport(0, 0, oldWidth, oldHeight);
+
+ QOpenGLShaderProgram *blitProgram = nullptr;
+ if (pex == nullptr) {
+ if (m_blitProgram == nullptr) {
+ m_blitProgram = new QOpenGLShaderProgram;
+ const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile;
+
+ {
+ QString source;
+#ifdef Q_OS_WASM
+ source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));
+#else
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));
+#endif
+ m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, source);
+ }
+
+ {
+ QString source;
+#ifdef Q_OS_WASM
+ source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));
+#else
+ source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));
+ source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));
+#endif
+ m_blitProgram->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, source);
+ }
+
+ m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+
+ m_blitProgram->link();
+
+ if (m_vao.isCreated()) {
+ m_vao.bind();
+ setupVertexAttribs();
+ }
+ }
+
+ if (m_vao.isCreated())
+ m_vao.bind();
+ else
+ setupVertexAttribs();
+
+ m_blitProgram->bind();
+ blitProgram = m_blitProgram;
+
+ } else {
+ pex->uploadData(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray, 8);
+ pex->uploadData(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray, 8);
+
+ pex->shaderManager->useBlitProgram();
+ blitProgram = pex->shaderManager->blitProgram();
+ }
+
+ blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
+
+ funcs->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ funcs->glBindTexture(GL_TEXTURE_2D, m_textureResource->m_texture);
+
+ funcs->glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+
+ funcs->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, 0);
+ funcs->glDeleteTextures(1, &tmp_texture);
+ funcs->glDeleteTextures(1, &oldTexture);
+
+ funcs->glBindFramebuffer(GL_FRAMEBUFFER, (GLuint)oldFbo);
+
+ if (pex != nullptr) {
+ funcs->glViewport(0, 0, pex->width, pex->height);
+ pex->updateClipScissorTest();
+ } else {
+ if (m_vao.isCreated()) {
+ m_vao.release();
+ } else {
+ m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
+ m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
+ }
+ }
+}
+
+void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx == nullptr) {
+ qWarning("QOpenGLTextureGlyphCache::fillTexture: Called with no context");
+ return;
+ }
+
+ if (ctx->d_func()->workaround_brokenFBOReadBack) {
+ QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
+ load_glyph_image_region_to_texture(ctx, image(), c.x, c.y, c.w, c.h, m_textureResource->m_texture, c.x, c.y);
+ return;
+ }
+
+ QImage mask = textureMapForGlyph(glyph, subPixelPosition);
+ load_glyph_image_to_texture(ctx, mask, m_textureResource->m_texture, c.x, c.y);
+}
+
+int QOpenGLTextureGlyphCache::glyphPadding() const
+{
+ return 1;
+}
+
+int QOpenGLTextureGlyphCache::maxTextureWidth() const
+{
+ QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ if (ctx == nullptr)
+ return QImageTextureGlyphCache::maxTextureWidth();
+ else
+ return ctx->d_func()->maxTextureSize();
+}
+
+int QOpenGLTextureGlyphCache::maxTextureHeight() const
+{
+ QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ if (ctx == nullptr)
+ return QImageTextureGlyphCache::maxTextureHeight();
+
+ if (ctx->d_func()->workaround_brokenTexSubImage)
+ return qMin(1024, ctx->d_func()->maxTextureSize());
+ else
+ return ctx->d_func()->maxTextureSize();
+}
+
+void QOpenGLTextureGlyphCache::clear()
+{
+ if (m_textureResource)
+ m_textureResource->free();
+ m_textureResource = nullptr;
+
+ delete m_blitProgram;
+ m_blitProgram = nullptr;
+
+ m_w = 0;
+ m_h = 0;
+ m_cx = 0;
+ m_cy = 0;
+ m_currentRowHeight = 0;
+ coords.clear();
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/qopengltextureglyphcache_p.h
index 7c12ce8998..15ecd6209b 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h
+++ b/src/opengl/qopengltextureglyphcache_p.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QTEXTUREGLYPHCACHE_GL_P_H
-#define QTEXTUREGLYPHCACHE_GL_P_H
+#ifndef QOPENGLTEXTUREGLYPHCACHE_P_H
+#define QOPENGLTEXTUREGLYPHCACHE_P_H
//
// W A R N I N G
@@ -51,46 +51,46 @@
// We mean it.
//
+#include <QtOpenGL/qtopenglglobal.h>
#include <private/qtextureglyphcache_p.h>
-#include <private/qgl_p.h>
-#include <qglshaderprogram.h>
-#include <qglframebufferobject.h>
+#include <private/qopenglcontext_p.h>
+#include <qopenglshaderprogram.h>
#include <qopenglfunctions.h>
+#include <qopenglbuffer.h>
+#include <qopenglvertexarrayobject.h>
// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
QT_BEGIN_NAMESPACE
-class QGL2PaintEngineExPrivate;
+class QOpenGL2PaintEngineExPrivate;
-struct QGLGlyphTexture : public QOpenGLSharedResource
+class QOpenGLGlyphTexture : public QOpenGLSharedResource
{
- QGLGlyphTexture(const QGLContext *ctx)
- : QOpenGLSharedResource(ctx->contextHandle()->shareGroup())
- , m_fbo(0)
+public:
+ explicit QOpenGLGlyphTexture(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
, m_width(0)
, m_height(0)
{
- if (ctx && QGLFramebufferObject::hasOpenGLFramebufferObjects() && !ctx->d_ptr->workaround_brokenFBOReadBack)
- ctx->contextHandle()->functions()->glGenFramebuffers(1, &m_fbo);
+ if (!ctx->d_func()->workaround_brokenFBOReadBack)
+ QOpenGLFunctions(ctx).glGenFramebuffers(1, &m_fbo);
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx);
+ qDebug(" -> QOpenGLGlyphTexture() %p for context %p.", this, ctx);
#endif
}
void freeResource(QOpenGLContext *context) override
{
- const QGLContext *ctx = QGLContext::fromOpenGLContext(context);
+ QOpenGLContext *ctx = context;
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
- qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx);
-#else
- Q_UNUSED(ctx);
+ qDebug("~QOpenGLGlyphTexture() %p for context %p.", this, ctx);
#endif
- if (ctx && m_fbo)
- ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &m_fbo);
+ if (!ctx->d_func()->workaround_brokenFBOReadBack)
+ ctx->functions()->glDeleteFramebuffers(1, &m_fbo);
if (m_width || m_height)
- ctx->contextHandle()->functions()->glDeleteTextures(1, &m_texture);
+ ctx->functions()->glDeleteTextures(1, &m_texture);
}
void invalidateResource() override
@@ -107,11 +107,11 @@ struct QGLGlyphTexture : public QOpenGLSharedResource
int m_height;
};
-class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache
+class Q_OPENGL_EXPORT QOpenGLTextureGlyphCache : public QImageTextureGlyphCache
{
public:
- QGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix);
- ~QGLTextureGlyphCache();
+ QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat glyphFormat, const QTransform &matrix, const QColor &color = QColor());
+ ~QOpenGLTextureGlyphCache();
virtual void createTextureData(int width, int height) override;
virtual void resizeTextureData(int width, int height) override;
@@ -121,23 +121,23 @@ public:
virtual int maxTextureHeight() const override;
inline GLuint texture() const {
- QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
- QGLGlyphTexture *glyphTexture = that->m_textureResource;
+ QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this);
+ QOpenGLGlyphTexture *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;
+ QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this);
+ QOpenGLGlyphTexture *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;
+ QOpenGLTextureGlyphCache *that = const_cast<QOpenGLTextureGlyphCache *>(this);
+ QOpenGLGlyphTexture *glyphTexture = that->m_textureResource;
return glyphTexture ? glyphTexture->m_height : 0;
}
- inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
+ inline void setPaintEnginePrivate(QOpenGL2PaintEngineExPrivate *p) { pex = p; }
inline const QOpenGLContextGroup *contextGroup() const { return m_textureResource ? m_textureResource->group() : nullptr; }
@@ -152,20 +152,30 @@ public:
void clear();
+ QOpenGL2PaintEngineExPrivate *paintEnginePrivate() const
+ {
+ return pex;
+ }
+
private:
- QGLGlyphTexture *m_textureResource;
+ void setupVertexAttribs();
- QGL2PaintEngineExPrivate *pex;
- QGLShaderProgram *m_blitProgram;
+ QOpenGLGlyphTexture *m_textureResource;
+
+ QOpenGL2PaintEngineExPrivate *pex;
+ QOpenGLShaderProgram *m_blitProgram;
FilterMode m_filterMode;
GLfloat m_vertexCoordinateArray[8];
GLfloat m_textureCoordinateArray[8];
int m_serialNumber;
+
+ QOpenGLBuffer m_buffer;
+ QOpenGLVertexArrayObject m_vao;
};
QT_END_NAMESPACE
-#endif
+#endif // QOPENGLTEXTUREGLYPHCACHE_P_H
diff --git a/src/opengl/qopengltexturehelper.cpp b/src/opengl/qopengltexturehelper.cpp
new file mode 100644
index 0000000000..8f1473ecc9
--- /dev/null
+++ b/src/opengl/qopengltexturehelper.cpp
@@ -0,0 +1,589 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qopengltexturehelper_p.h"
+
+#include <QOpenGLContext>
+#include <private/qopenglextensions_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
+{
+ functions = context->functions();
+ // Resolve EXT_direct_state_access entry points if present.
+
+ // However, disable it on some systems where DSA is known to be unreliable.
+ bool allowDSA = true;
+ const char *renderer = reinterpret_cast<const char *>(context->functions()->glGetString(GL_RENDERER));
+ // QTBUG-40653, QTBUG-44988
+ if (renderer && strstr(renderer, "AMD Radeon HD"))
+ allowDSA = false;
+
+ if (allowDSA && !context->isOpenGLES()
+ && context->hasExtension(QByteArrayLiteral("GL_EXT_direct_state_access"))) {
+ TextureParameteriEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , GLint )>(context->getProcAddress("glTextureParameteriEXT"));
+ TextureParameterivEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , const GLint *)>(context->getProcAddress("glTextureParameterivEXT"));
+ TextureParameterfEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , GLfloat )>(context->getProcAddress("glTextureParameterfEXT"));
+ TextureParameterfvEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLenum , const GLfloat *)>(context->getProcAddress("glTextureParameterfvEXT"));
+ GenerateTextureMipmapEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum )>(context->getProcAddress("glGenerateTextureMipmapEXT"));
+ TextureStorage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei )>(context->getProcAddress("glTextureStorage3DEXT"));
+ TextureStorage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei )>(context->getProcAddress("glTextureStorage2DEXT"));
+ TextureStorage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei )>(context->getProcAddress("glTextureStorage1DEXT"));
+ TextureStorage3DMultisampleEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureStorage3DMultisampleEXT"));
+ TextureStorage2DMultisampleEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureStorage2DMultisampleEXT"));
+ TextureImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage3DEXT"));
+ TextureImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage2DEXT"));
+ TextureImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureImage1DEXT"));
+ TextureSubImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage3DEXT"));
+ TextureSubImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage2DEXT"));
+ TextureSubImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTextureSubImage1DEXT"));
+ CompressedTextureSubImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage1DEXT"));
+ CompressedTextureSubImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage2DEXT"));
+ CompressedTextureSubImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureSubImage3DEXT"));
+ CompressedTextureImage1DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage1DEXT"));
+ CompressedTextureImage2DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage2DEXT"));
+ CompressedTextureImage3DEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTextureImage3DEXT"));
+
+ // Use the real DSA functions
+ TextureParameteri = &QOpenGLTextureHelper::dsa_TextureParameteri;
+ TextureParameteriv = &QOpenGLTextureHelper::dsa_TextureParameteriv;
+ TextureParameterf = &QOpenGLTextureHelper::dsa_TextureParameterf;
+ TextureParameterfv = &QOpenGLTextureHelper::dsa_TextureParameterfv;
+ GenerateTextureMipmap = &QOpenGLTextureHelper::dsa_GenerateTextureMipmap;
+ TextureStorage3D = &QOpenGLTextureHelper::dsa_TextureStorage3D;
+ TextureStorage2D = &QOpenGLTextureHelper::dsa_TextureStorage2D;
+ TextureStorage1D = &QOpenGLTextureHelper::dsa_TextureStorage1D;
+ TextureStorage3DMultisample = &QOpenGLTextureHelper::dsa_TextureStorage3DMultisample;
+ TextureStorage2DMultisample = &QOpenGLTextureHelper::dsa_TextureStorage2DMultisample;
+ TextureImage3D = &QOpenGLTextureHelper::dsa_TextureImage3D;
+ TextureImage2D = &QOpenGLTextureHelper::dsa_TextureImage2D;
+ TextureImage1D = &QOpenGLTextureHelper::dsa_TextureImage1D;
+ TextureSubImage3D = &QOpenGLTextureHelper::dsa_TextureSubImage3D;
+ TextureSubImage2D = &QOpenGLTextureHelper::dsa_TextureSubImage2D;
+ TextureSubImage1D = &QOpenGLTextureHelper::dsa_TextureSubImage1D;
+ CompressedTextureSubImage1D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage1D;
+ CompressedTextureSubImage2D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage2D;
+ CompressedTextureSubImage3D = &QOpenGLTextureHelper::dsa_CompressedTextureSubImage3D;
+ CompressedTextureImage1D = &QOpenGLTextureHelper::dsa_CompressedTextureImage1D;
+ CompressedTextureImage2D = &QOpenGLTextureHelper::dsa_CompressedTextureImage2D;
+ CompressedTextureImage3D = &QOpenGLTextureHelper::dsa_CompressedTextureImage3D;
+ } else {
+ // Use our own DSA emulation
+ TextureParameteri = &QOpenGLTextureHelper::qt_TextureParameteri;
+ TextureParameteriv = &QOpenGLTextureHelper::qt_TextureParameteriv;
+ TextureParameterf = &QOpenGLTextureHelper::qt_TextureParameterf;
+ TextureParameterfv = &QOpenGLTextureHelper::qt_TextureParameterfv;
+ GenerateTextureMipmap = &QOpenGLTextureHelper::qt_GenerateTextureMipmap;
+ TextureStorage3D = &QOpenGLTextureHelper::qt_TextureStorage3D;
+ TextureStorage2D = &QOpenGLTextureHelper::qt_TextureStorage2D;
+ TextureStorage1D = &QOpenGLTextureHelper::qt_TextureStorage1D;
+ TextureStorage3DMultisample = &QOpenGLTextureHelper::qt_TextureStorage3DMultisample;
+ TextureStorage2DMultisample = &QOpenGLTextureHelper::qt_TextureStorage2DMultisample;
+ TextureImage3D = &QOpenGLTextureHelper::qt_TextureImage3D;
+ TextureImage2D = &QOpenGLTextureHelper::qt_TextureImage2D;
+ TextureImage1D = &QOpenGLTextureHelper::qt_TextureImage1D;
+ TextureSubImage3D = &QOpenGLTextureHelper::qt_TextureSubImage3D;
+ TextureSubImage2D = &QOpenGLTextureHelper::qt_TextureSubImage2D;
+ TextureSubImage1D = &QOpenGLTextureHelper::qt_TextureSubImage1D;
+ CompressedTextureSubImage1D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage1D;
+ CompressedTextureSubImage2D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage2D;
+ CompressedTextureSubImage3D = &QOpenGLTextureHelper::qt_CompressedTextureSubImage3D;
+ CompressedTextureImage1D = &QOpenGLTextureHelper::qt_CompressedTextureImage1D;
+ CompressedTextureImage2D = &QOpenGLTextureHelper::qt_CompressedTextureImage2D;
+ CompressedTextureImage3D = &QOpenGLTextureHelper::qt_CompressedTextureImage3D;
+ }
+
+ // Some DSA functions are part of NV_texture_multisample instead
+ if (!context->isOpenGLES()
+ && context->hasExtension(QByteArrayLiteral("GL_NV_texture_multisample"))) {
+ TextureImage3DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureImage3DMultisampleNV"));
+ TextureImage2DMultisampleNV = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLsizei , GLint , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTextureImage2DMultisampleNV"));
+
+ TextureImage3DMultisample = &QOpenGLTextureHelper::dsa_TextureImage3DMultisample;
+ TextureImage2DMultisample = &QOpenGLTextureHelper::dsa_TextureImage2DMultisample;
+ } else {
+ TextureImage3DMultisample = &QOpenGLTextureHelper::qt_TextureImage3DMultisample;
+ TextureImage2DMultisample = &QOpenGLTextureHelper::qt_TextureImage2DMultisample;
+ }
+
+#if defined(QT_OPENGL_ES_2)
+ // Here we are targeting OpenGL ES 2.0+ only. This is likely using EGL, where,
+ // similarly to WGL, non-extension functions (i.e. any function that is part of the
+ // GLES spec) *may* not be queried via eglGetProcAddress.
+
+ // OpenGL 1.0
+ TexImage1D = 0;
+
+ // OpenGL 1.1
+ TexSubImage1D = 0;
+
+ // OpenGL 1.3
+ GetCompressedTexImage = 0;
+ CompressedTexSubImage1D = 0;
+ CompressedTexSubImage2D = ::glCompressedTexSubImage2D;
+ CompressedTexImage1D = 0;
+ CompressedTexImage2D = ::glCompressedTexImage2D;
+ ActiveTexture = ::glActiveTexture;
+
+ // OpenGL 3.0
+ GenerateMipmap = ::glGenerateMipmap;
+
+ // OpenGL 3.2
+ TexImage3DMultisample = 0;
+ TexImage2DMultisample = 0;
+
+ // OpenGL 4.2
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx->format().majorVersion() >= 3) {
+ // OpenGL ES 3.0+ has immutable storage for 2D and 3D at least.
+ QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d();
+ TexStorage3D = extra->f.TexStorage3D;
+ TexStorage2D = extra->f.TexStorage2D;
+ } else {
+ TexStorage3D = 0;
+ TexStorage2D = 0;
+ }
+ TexStorage1D = 0;
+
+ // OpenGL 4.3
+ TexStorage3DMultisample = 0;
+ TexStorage2DMultisample = 0;
+ TexBufferRange = 0;
+ TextureView = 0;
+
+ // OpenGL ES 3.1+ has TexStorage2DMultisample
+ if (ctx->format().version() >= qMakePair(3, 1)) {
+ QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d();
+ TexStorage2DMultisample = extra->f.TexStorage2DMultisample;
+ }
+
+#endif
+
+ if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"))) {
+ TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid*)>(context->getProcAddress("glTexImage3DOES"));
+ TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const GLvoid*)>(context->getProcAddress("glTexSubImage3DOES"));
+ CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const GLvoid*)>(context->getProcAddress("glCompressedTexImage3DOES"));
+ CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const GLvoid*)>(context->getProcAddress("glCompressedTexSubImage3DOES"));
+ } else {
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx->isOpenGLES() && ctx->format().majorVersion() >= 3) {
+ // OpenGL ES 3.0+ has glTexImage3D.
+ QOpenGLExtraFunctionsPrivate *extra = static_cast<QOpenGLExtensions *>(context->extraFunctions())->d();
+ TexImage3D = extra->f.TexImage3D;
+ TexSubImage3D = extra->f.TexSubImage3D;
+ CompressedTexImage3D = extra->f.CompressedTexImage3D;
+ CompressedTexSubImage3D = extra->f.CompressedTexSubImage3D;
+ } else {
+ // OpenGL 1.2
+ TexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexImage3D"));
+ TexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexSubImage3D"));
+
+ // OpenGL 1.3
+ CompressedTexImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage3D"));
+ CompressedTexSubImage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLint , GLsizei , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage3D"));
+ }
+ }
+
+#ifndef QT_OPENGL_ES_2
+ // OpenGL 1.0 and 1.1
+ TexImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexImage1D"));
+ TexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLenum , const GLvoid *)>(context->getProcAddress("glTexSubImage1D"));\
+
+ // OpenGL 1.3
+ GetCompressedTexImage = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLvoid *)>(context->getProcAddress("glGetCompressedTexImage"));
+ CompressedTexSubImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage1D"));
+ CompressedTexSubImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLint , GLsizei , GLsizei , GLenum , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexSubImage2D"));
+ CompressedTexImage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage1D"));
+ CompressedTexImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLenum , GLsizei , GLsizei , GLint , GLsizei , const GLvoid *)>(context->getProcAddress("glCompressedTexImage2D"));
+ ActiveTexture = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glActiveTexture"));
+
+ // OpenGL 3.0
+ GenerateMipmap = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum )>(context->getProcAddress("glGenerateMipmap"));
+
+ // OpenGL 3.2
+ TexImage3DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLint , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexImage3DMultisample"));
+ TexImage2DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLint , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexImage2DMultisample"));
+
+ // OpenGL 4.2
+ TexStorage3D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei )>(context->getProcAddress("glTexStorage3D"));
+ TexStorage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei )>(context->getProcAddress("glTexStorage2D"));
+ TexStorage1D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei )>(context->getProcAddress("glTexStorage1D"));
+
+ // OpenGL 4.3
+ TexStorage3DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexStorage3DMultisample"));
+ TexStorage2DMultisample = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLsizei , GLenum , GLsizei , GLsizei , GLboolean )>(context->getProcAddress("glTexStorage2DMultisample"));
+ TexBufferRange = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLenum , GLuint , GLintptr , GLsizeiptr )>(context->getProcAddress("glTexBufferRange"));
+ TextureView = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint , GLenum , GLuint , GLuint , GLuint , GLuint )>(context->getProcAddress("glTextureView"));
+#endif
+}
+
+void QOpenGLTextureHelper::dsa_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param)
+{
+ Q_UNUSED(bindingTarget);
+ TextureParameteriEXT(texture, target, pname, param);
+}
+
+void QOpenGLTextureHelper::dsa_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params)
+{
+ Q_UNUSED(bindingTarget);
+ TextureParameterivEXT(texture, target, pname, params);
+}
+
+void QOpenGLTextureHelper::dsa_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param)
+{
+ Q_UNUSED(bindingTarget);
+ TextureParameterfEXT(texture, target, pname, param);
+}
+
+void QOpenGLTextureHelper::dsa_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params)
+{
+ Q_UNUSED(bindingTarget);
+ TextureParameterfvEXT(texture, target, pname, params);
+}
+
+void QOpenGLTextureHelper::dsa_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget)
+{
+ Q_UNUSED(bindingTarget);
+ GenerateTextureMipmapEXT(texture, target);
+}
+
+void QOpenGLTextureHelper::dsa_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ Q_UNUSED(bindingTarget);
+ TextureStorage3DEXT(texture, target, levels, internalFormat, width, height, depth);
+}
+
+void QOpenGLTextureHelper::dsa_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ Q_UNUSED(bindingTarget);
+ TextureStorage2DEXT(texture, target, levels, internalFormat, width, height);
+}
+
+void QOpenGLTextureHelper::dsa_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width)
+{
+ Q_UNUSED(bindingTarget);
+ TextureStorage1DEXT(texture, target, levels, internalFormat, width);
+}
+
+void QOpenGLTextureHelper::dsa_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+{
+ Q_UNUSED(bindingTarget);
+ TextureStorage3DMultisampleEXT(texture, target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::dsa_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+{
+ Q_UNUSED(bindingTarget);
+ TextureStorage2DMultisampleEXT(texture, target, samples, internalFormat, width, height, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::dsa_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureImage3DEXT(texture, target, level, internalFormat, width, height, depth, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureImage2DEXT(texture, target, level, internalFormat, width, height, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureImage1DEXT(texture, target, level, internalFormat, width, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ Q_UNUSED(bindingTarget);
+ TextureSubImage1DEXT(texture, target, level, xoffset, width, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::dsa_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+{
+ Q_UNUSED(bindingTarget);
+ TextureImage3DMultisampleNV(texture, target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::dsa_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+{
+ Q_UNUSED(bindingTarget);
+ TextureImage2DMultisampleNV(texture, target, samples, internalFormat, width, height, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureSubImage1DEXT(texture, target, level, xoffset, width, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureSubImage2DEXT(texture, target, level, xoffset, yoffset, width, height, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureSubImage3DEXT(texture, target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureImage1DEXT(texture, target, level, internalFormat, width, border, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureImage2DEXT(texture, target, level, internalFormat, width, height, border, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::dsa_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ Q_UNUSED(bindingTarget);
+ CompressedTextureImage3DEXT(texture, target, level, internalFormat, width, height, depth, border, imageSize, bits);
+}
+
+namespace {
+
+class TextureBinder
+{
+public:
+ TextureBinder(QOpenGLFunctions *functions, GLuint texture, GLenum target, GLenum bindingTarget)
+ : m_functions(functions)
+ {
+ // For cubemaps we can't use the standard DSA emulation as it is illegal to
+ // try to bind a texture to one of the cubemap face targets. So we force the
+ // target and binding target to the cubemap values in this case.
+ switch (target) {
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+ case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+ case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+ bindingTarget = GL_TEXTURE_BINDING_CUBE_MAP;
+ m_target = GL_TEXTURE_CUBE_MAP;
+ break;
+
+ default:
+ m_target = target;
+ break;
+ }
+
+ m_functions->glGetIntegerv(bindingTarget, &m_oldTexture);
+ m_functions->glBindTexture(m_target, texture);
+ }
+
+ ~TextureBinder()
+ {
+ m_functions->glBindTexture(m_target, m_oldTexture);
+ }
+
+private:
+ QOpenGLFunctions *m_functions;
+ GLenum m_target;
+ GLint m_oldTexture;
+};
+
+} // namespace
+
+void QOpenGLTextureHelper::qt_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexParameteri(target, pname, param);
+}
+
+void QOpenGLTextureHelper::qt_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexParameteriv(target, pname, params);
+}
+
+void QOpenGLTextureHelper::qt_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexParameterf(target, pname, param);
+}
+
+void QOpenGLTextureHelper::qt_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexParameterfv(target, pname, params);
+}
+
+void QOpenGLTextureHelper::qt_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glGenerateMipmap(target);
+}
+
+void QOpenGLTextureHelper::qt_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexStorage3D(target, levels, internalFormat, width, height, depth);
+}
+
+void QOpenGLTextureHelper::qt_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexStorage2D(target, levels, internalFormat, width, height);
+}
+
+void QOpenGLTextureHelper::qt_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexStorage1D(target, levels, internalFormat, width);
+}
+
+void QOpenGLTextureHelper::qt_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexStorage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::qt_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexStorage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::qt_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexImage2D(target, level, internalFormat, width, height, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexImage1D(target, level, internalFormat, width, border, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ functions->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexSubImage1D(target, level, xoffset, width, format, type, pixels);
+}
+
+void QOpenGLTextureHelper::qt_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexImage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::qt_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexImage1D(target, level, internalFormat, width, border, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, bits);
+}
+
+void QOpenGLTextureHelper::qt_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits)
+{
+ TextureBinder binder(functions, texture, target, bindingTarget);
+ glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, bits);
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopengltexturehelper_p.h b/src/opengl/qopengltexturehelper_p.h
new file mode 100644
index 0000000000..a62a47d029
--- /dev/null
+++ b/src/opengl/qopengltexturehelper_p.h
@@ -0,0 +1,797 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QOPENGLTEXTUREHELPER_P_H
+#define QOPENGLTEXTUREHELPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#ifndef QT_NO_OPENGL
+
+#include "qopengl.h"
+#include "qopenglpixeltransferoptions.h"
+#include "qopengltexture.h"
+#include "qopenglfunctions.h"
+
+QT_BEGIN_NAMESPACE
+
+// Constants for OpenGL and OpenGL ES 3.0+ which are not available with OpenGL ES 2.0.
+#ifndef GL_TEXTURE_BASE_LEVEL
+#define GL_TEXTURE_BASE_LEVEL 0x813C
+#endif
+#ifndef GL_TEXTURE_MAX_LEVEL
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#endif
+#ifndef GL_TEXTURE_COMPARE_MODE
+#define GL_TEXTURE_COMPARE_MODE 0x884C
+#endif
+#ifndef GL_TEXTURE_COMPARE_FUNC
+#define GL_TEXTURE_COMPARE_FUNC 0x884D
+#endif
+
+// use GL_APICALL only on Android + __clang__
+#if !defined(Q_OS_ANDROID) || !defined(__clang__)
+# undef GL_APICALL
+# define GL_APICALL
+#elif !defined(GL_APICALL)
+# define GL_APICALL
+#endif
+
+class QOpenGLContext;
+
+class QOpenGLTextureHelper
+{
+public:
+ QOpenGLTextureHelper(QOpenGLContext *context);
+
+ // DSA-like API. Will either use real DSA or our emulation
+ inline void glTextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param)
+ {
+ (this->*TextureParameteri)(texture, target, bindingTarget, pname, param);
+ }
+
+ inline void glTextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params)
+ {
+ (this->*TextureParameteriv)(texture, target, bindingTarget, pname, params);
+ }
+
+ inline void glTextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param)
+ {
+ (this->*TextureParameterf)(texture, target, bindingTarget, pname, param);
+ }
+
+ inline void glTextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params)
+ {
+ (this->*TextureParameterfv)(texture, target, bindingTarget, pname, params);
+ }
+
+ inline void glGenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget)
+ {
+ (this->*GenerateTextureMipmap)(texture, target, bindingTarget);
+ }
+
+ inline void glTextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth)
+ {
+ (this->*TextureStorage3D)(texture, target, bindingTarget, levels, internalFormat, width, height, depth);
+ }
+
+ inline void glTextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width, GLsizei height)
+ {
+ (this->*TextureStorage2D)(texture, target, bindingTarget, levels, internalFormat, width, height);
+ }
+
+ inline void glTextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width)
+ {
+ (this->*TextureStorage1D)(texture, target, bindingTarget, levels, internalFormat, width);
+ }
+
+ inline void glTextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+ {
+ (this->*TextureStorage3DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, depth, fixedSampleLocations);
+ }
+
+ inline void glTextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+ {
+ (this->*TextureStorage2DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, fixedSampleLocations);
+ }
+
+ inline void glTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ (this->*TextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, format, type, pixels);
+ }
+
+ inline void glTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ (this->*TextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, format, type, pixels);
+ }
+
+ inline void glTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ (this->*TextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, format, type, pixels);
+ }
+
+ inline void glTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*TextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*TextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+ }
+ }
+
+ inline void glTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLenum format, GLenum type,
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*TextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, type, pixels);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*TextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, type, pixels);
+ }
+ }
+
+ inline void glTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type,
+ const GLvoid *pixels, const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*TextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, type, pixels);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*TextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, type, pixels);
+ }
+ }
+
+ inline void glTextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+ {
+ (this->*TextureImage3DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, depth, fixedSampleLocations);
+ }
+
+ inline void glTextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+ {
+ (this->*TextureImage2DMultisample)(texture, target, bindingTarget, samples, internalFormat, width, height, fixedSampleLocations);
+ }
+
+ inline void glCompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureSubImage1D)(texture, target, bindingTarget, level, xoffset, width, format, imageSize, bits);
+ }
+ }
+
+ inline void glCompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureSubImage2D)(texture, target, bindingTarget, level, xoffset, yoffset, width, height, format, imageSize, bits);
+ }
+ }
+
+ inline void glCompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureSubImage3D)(texture, target, bindingTarget, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, bits);
+ }
+ }
+
+ inline void glCompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage1D)(texture, target, bindingTarget, level, internalFormat, width, border, imageSize, bits);
+ }
+ }
+
+ inline void glCompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage2D)(texture, target, bindingTarget, level, internalFormat, width, height, border, imageSize, bits);
+ }
+ }
+
+ inline void glCompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLsizei imageSize, const GLvoid *bits,
+ const QOpenGLPixelTransferOptions * const options = nullptr)
+ {
+ if (options) {
+ QOpenGLPixelTransferOptions oldOptions = savePixelUploadOptions();
+ setPixelUploadOptions(*options);
+ (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits);
+ setPixelUploadOptions(oldOptions);
+ } else {
+ (this->*CompressedTextureImage3D)(texture, target, bindingTarget, level, internalFormat, width, height, depth, border, imageSize, bits);
+ }
+ }
+
+private:
+ // DSA wrapper (so we can use pointer to member function as switch)
+ void dsa_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param);
+
+ void dsa_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params);
+
+ void dsa_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param);
+
+ void dsa_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params);
+
+ void dsa_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget);
+
+ void dsa_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth);
+
+ void dsa_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width, GLsizei height);
+
+ void dsa_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat,
+ GLsizei width);
+
+ void dsa_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+
+ void dsa_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+
+ void dsa_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+
+ void dsa_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+
+ void dsa_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+
+ void dsa_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLsizei imageSize, const GLvoid *bits);
+
+ void dsa_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize, const GLvoid *bits);
+
+ void dsa_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const GLvoid *bits);
+
+ void dsa_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize, const GLvoid *bits);
+
+ void dsa_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLint border, GLsizei imageSize, const GLvoid *bits);
+
+ void dsa_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLsizei imageSize, const GLvoid *bits);
+
+ // DSA emulation API
+ void qt_TextureParameteri(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param);
+
+ void qt_TextureParameteriv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params);
+
+ void qt_TextureParameterf(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param);
+
+ void qt_TextureParameterfv(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params);
+
+ void qt_GenerateTextureMipmap(GLuint texture, GLenum target, GLenum bindingTarget);
+
+ void qt_TextureStorage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels,
+ GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth);
+
+ void qt_TextureStorage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels,
+ GLenum internalFormat, GLsizei width, GLsizei height);
+
+ void qt_TextureStorage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels,
+ GLenum internalFormat, GLsizei width);
+
+ void qt_TextureStorage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLsizei depth, GLboolean fixedSampleLocations);
+
+ void qt_TextureStorage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples,
+ GLenum internalFormat, GLsizei width, GLsizei height,
+ GLboolean fixedSampleLocations);
+
+ void qt_TextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels);
+
+ void qt_TextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels);
+
+ void qt_TextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLint border, GLenum format, GLenum type,
+ const GLvoid *pixels);
+
+ void qt_TextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type, const GLvoid *pixels);
+
+ void qt_TextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels);
+
+ void qt_TextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLsizei width,
+ GLenum format, GLenum type, const GLvoid *pixels);
+
+ void qt_TextureImage3DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples,
+ GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth,
+ GLboolean fixedSampleLocations);
+
+ void qt_TextureImage2DMultisample(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples,
+ GLint internalFormat, GLsizei width, GLsizei height,
+ GLboolean fixedSampleLocations);
+
+ void qt_CompressedTextureSubImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLsizei width, GLenum format,
+ GLsizei imageSize, const GLvoid *bits);
+
+ void qt_CompressedTextureSubImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize, const GLvoid *bits);
+
+ void qt_CompressedTextureSubImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLsizei imageSize, const GLvoid *bits);
+
+ void qt_CompressedTextureImage1D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLint border,
+ GLsizei imageSize, const GLvoid *bits);
+
+ void qt_CompressedTextureImage2D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLsizei imageSize, const GLvoid *bits);
+
+ void qt_CompressedTextureImage3D(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border,
+ GLsizei imageSize, const GLvoid *bits);
+
+public:
+ // Raw OpenGL functions, resolved and used by our DSA-like static functions if no EXT_direct_state_access is available
+
+ // OpenGL 1.0
+ inline void glTexImage1D(GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ TexImage1D(target, level, internalFormat, width, border, format, type, pixels);
+ }
+
+ // OpenGL 1.1
+ inline void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width,
+ GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ TexSubImage1D(target, level, xoffset, width, format, type, pixels);
+ }
+
+ // OpenGL 1.2
+ inline void glTexImage3D(GLenum target, GLint level, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border,
+ GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ TexImage3D(target, level, internalFormat, width, height, depth, border, format, type, pixels);
+ }
+
+ inline void glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels)
+ {
+ TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+ }
+
+ // OpenGL 1.3
+ inline void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *img)
+ {
+ GetCompressedTexImage(target, level, img);
+ }
+
+ inline void glCompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width,
+ GLenum format, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data);
+ }
+
+ inline void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+ }
+
+ inline void glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+ }
+
+ inline void glCompressedTexImage1D(GLenum target, GLint level, GLenum internalFormat, GLsizei width,
+ GLint border, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexImage1D(target, level, internalFormat, width, border, imageSize, data);
+ }
+
+ inline void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height,
+ GLint border, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexImage2D(target, level, internalFormat, width, height, border, imageSize, data);
+ }
+
+ inline void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLsizei imageSize, const GLvoid *data)
+ {
+ CompressedTexImage3D(target, level, internalFormat, width, height, depth, border, imageSize, data);
+ }
+
+ inline void glActiveTexture(GLenum texture)
+ {
+ ActiveTexture(texture);
+ }
+
+ // OpenGL 3.0
+ inline void glGenerateMipmap(GLenum target)
+ {
+ GenerateMipmap(target);
+ }
+
+ // OpenGL 3.2
+ inline void glTexImage3DMultisample(GLenum target, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLboolean fixedSampleLocations)
+ {
+ TexImage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+ }
+
+ inline void glTexImage2DMultisample(GLenum target, GLsizei samples, GLint internalFormat,
+ GLsizei width, GLsizei height,
+ GLboolean fixedSampleLocations)
+ {
+ TexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations);
+ }
+
+ // OpenGL 4.2
+ inline void glTexStorage3D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth)
+ {
+ TexStorage3D(target, levels, internalFormat, width, height, depth);
+ }
+
+ inline void glTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height)
+ {
+ TexStorage2D(target, levels, internalFormat, width, height);
+ }
+
+ inline void glTexStorage1D(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width)
+ {
+ TexStorage1D(target, levels, internalFormat, width);
+ }
+
+ // OpenGL 4.3
+ inline void glTexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations)
+ {
+ TexStorage3DMultisample(target, samples, internalFormat, width, height, depth, fixedSampleLocations);
+ }
+
+ inline void glTexStorage2DMultisample(GLenum target, GLsizei samples, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLboolean fixedSampleLocations)
+ {
+ TexStorage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations);
+ }
+
+ inline void glTexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
+ GLintptr offset, GLsizeiptr size)
+ {
+ TexBufferRange(target, internalFormat, buffer, offset, size);
+ }
+
+ inline void glTextureView(GLuint texture, GLenum target, GLuint origTexture, GLenum internalFormat,
+ GLuint minLevel, GLuint numLevels, GLuint minLayer, GLuint numLayers)
+ {
+ TextureView(texture, target, origTexture, internalFormat, minLevel, numLevels, minLayer, numLayers);
+ }
+
+ // Helper functions
+ inline QOpenGLPixelTransferOptions savePixelUploadOptions()
+ {
+ QOpenGLPixelTransferOptions options;
+ int val = 0;
+ functions->glGetIntegerv(GL_UNPACK_ALIGNMENT, &val);
+ options.setAlignment(val);
+#if !defined(QT_OPENGL_ES_2)
+ functions->glGetIntegerv(GL_UNPACK_SKIP_IMAGES, &val);
+ options.setSkipImages(val);
+ functions->glGetIntegerv(GL_UNPACK_SKIP_ROWS, &val);
+ options.setSkipRows(val);
+ functions->glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &val);
+ options.setSkipPixels(val);
+ functions->glGetIntegerv(GL_UNPACK_IMAGE_HEIGHT, &val);
+ options.setImageHeight(val);
+ functions->glGetIntegerv(GL_UNPACK_ROW_LENGTH, &val);
+ options.setRowLength(val);
+ GLboolean b = GL_FALSE;
+ functions->glGetBooleanv(GL_UNPACK_LSB_FIRST, &b);
+ options.setLeastSignificantByteFirst(b);
+ functions->glGetBooleanv(GL_UNPACK_SWAP_BYTES, &b);
+ options.setSwapBytesEnabled(b);
+#endif
+ return options;
+ }
+
+ inline void setPixelUploadOptions(const QOpenGLPixelTransferOptions &options)
+ {
+ functions->glPixelStorei(GL_UNPACK_ALIGNMENT, options.alignment());
+#if !defined(QT_OPENGL_ES_2)
+ functions->glPixelStorei(GL_UNPACK_SKIP_IMAGES, options.skipImages());
+ functions->glPixelStorei(GL_UNPACK_SKIP_ROWS, options.skipRows());
+ functions->glPixelStorei(GL_UNPACK_SKIP_PIXELS, options.skipPixels());
+ functions->glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, options.imageHeight());
+ functions->glPixelStorei(GL_UNPACK_ROW_LENGTH, options.rowLength());
+ functions->glPixelStorei(GL_UNPACK_LSB_FIRST, options.isLeastSignificantBitFirst());
+ functions->glPixelStorei(GL_UNPACK_SWAP_BYTES, options.isSwapBytesEnabled());
+#endif
+ }
+
+ QOpenGLFunctions *functions;
+private:
+ // Typedefs and pointers to member functions used to switch between EXT_direct_state_access and our own emulated DSA.
+ // The argument match the corresponding GL function, but there's an extra "GLenum bindingTarget" which gets used with
+ // the DSA emulation -- it contains the right GL_BINDING_TEXTURE_X to use.
+ typedef void (QOpenGLTextureHelper::*TextureParameteriMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLint param);
+ typedef void (QOpenGLTextureHelper::*TextureParameterivMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLint *params);
+ typedef void (QOpenGLTextureHelper::*TextureParameterfMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, GLfloat param);
+ typedef void (QOpenGLTextureHelper::*TextureParameterfvMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLenum pname, const GLfloat *params);
+ typedef void (QOpenGLTextureHelper::*GenerateTextureMipmapMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget);
+ typedef void (QOpenGLTextureHelper::*TextureStorage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth);
+ typedef void (QOpenGLTextureHelper::*TextureStorage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height);
+ typedef void (QOpenGLTextureHelper::*TextureStorage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei levels, GLenum internalFormat, GLsizei width);
+ typedef void (QOpenGLTextureHelper::*TextureStorage3DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ typedef void (QOpenGLTextureHelper::*TextureStorage2DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+ typedef void (QOpenGLTextureHelper::*TextureImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureSubImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureSubImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureSubImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+ typedef void (QOpenGLTextureHelper::*TextureImage3DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ typedef void (QOpenGLTextureHelper::*TextureImage2DMultisampleMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureSubImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureImage1DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureImage2DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+ typedef void (QOpenGLTextureHelper::*CompressedTextureImage3DMemberFunc)(GLuint texture, GLenum target, GLenum bindingTarget, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+
+
+ TextureParameteriMemberFunc TextureParameteri;
+ TextureParameterivMemberFunc TextureParameteriv;
+ TextureParameterfMemberFunc TextureParameterf;
+ TextureParameterfvMemberFunc TextureParameterfv;
+ GenerateTextureMipmapMemberFunc GenerateTextureMipmap;
+ TextureStorage3DMemberFunc TextureStorage3D;
+ TextureStorage2DMemberFunc TextureStorage2D;
+ TextureStorage1DMemberFunc TextureStorage1D;
+ TextureStorage3DMultisampleMemberFunc TextureStorage3DMultisample;
+ TextureStorage2DMultisampleMemberFunc TextureStorage2DMultisample;
+ TextureImage3DMemberFunc TextureImage3D;
+ TextureImage2DMemberFunc TextureImage2D;
+ TextureImage1DMemberFunc TextureImage1D;
+ TextureSubImage3DMemberFunc TextureSubImage3D;
+ TextureSubImage2DMemberFunc TextureSubImage2D;
+ TextureSubImage1DMemberFunc TextureSubImage1D;
+ TextureImage3DMultisampleMemberFunc TextureImage3DMultisample;
+ TextureImage2DMultisampleMemberFunc TextureImage2DMultisample;
+ CompressedTextureSubImage1DMemberFunc CompressedTextureSubImage1D;
+ CompressedTextureSubImage2DMemberFunc CompressedTextureSubImage2D;
+ CompressedTextureSubImage3DMemberFunc CompressedTextureSubImage3D;
+ CompressedTextureImage1DMemberFunc CompressedTextureImage1D;
+ CompressedTextureImage2DMemberFunc CompressedTextureImage2D;
+ CompressedTextureImage3DMemberFunc CompressedTextureImage3D;
+
+ // Raw function pointers for core and DSA functions
+
+ // EXT_direct_state_access used when DSA is available
+ void (QOPENGLF_APIENTRYP TextureParameteriEXT)(GLuint texture, GLenum target, GLenum pname, GLint param);
+ void (QOPENGLF_APIENTRYP TextureParameterivEXT)(GLuint texture, GLenum target, GLenum pname, const GLint *params);
+ void (QOPENGLF_APIENTRYP TextureParameterfEXT)(GLuint texture, GLenum target, GLenum pname, GLfloat param);
+ void (QOPENGLF_APIENTRYP TextureParameterfvEXT)(GLuint texture, GLenum target, GLenum pname, const GLfloat *params);
+ void (QOPENGLF_APIENTRYP GenerateTextureMipmapEXT)(GLuint texture, GLenum target);
+ void (QOPENGLF_APIENTRYP TextureStorage3DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth);
+ void (QOPENGLF_APIENTRYP TextureStorage2DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height);
+ void (QOPENGLF_APIENTRYP TextureStorage1DEXT)(GLuint texture, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width);
+ void (QOPENGLF_APIENTRYP TextureStorage3DMultisampleEXT)(GLuint texture, GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TextureStorage2DMultisampleEXT)(GLuint texture, GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TextureImage3DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TextureImage2DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TextureImage1DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TextureSubImage3DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TextureSubImage2DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TextureSubImage1DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP CompressedTextureSubImage1DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ void (QOPENGLF_APIENTRYP CompressedTextureSubImage2DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ void (QOPENGLF_APIENTRYP CompressedTextureSubImage3DEXT)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *bits);
+ void (QOPENGLF_APIENTRYP CompressedTextureImage1DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *bits);
+ void (QOPENGLF_APIENTRYP CompressedTextureImage2DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *bits);
+ void (QOPENGLF_APIENTRYP CompressedTextureImage3DEXT)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *bits);
+
+
+ // Plus some missing ones that are in the NV_texture_multisample extension instead
+ void (QOPENGLF_APIENTRYP TextureImage3DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TextureImage2DMultisampleNV)(GLuint texture, GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+
+ // OpenGL 1.0
+ void (QOPENGLF_APIENTRYP TexImage1D)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+
+ // OpenGL 1.1
+ void (QOPENGLF_APIENTRYP TexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+
+ // OpenGL 1.2
+ void (QOPENGLF_APIENTRYP TexImage3D)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+ void (QOPENGLF_APIENTRYP TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
+
+ // OpenGL 1.3
+ void (QOPENGLF_APIENTRYP GetCompressedTexImage)(GLenum target, GLint level, GLvoid *img);
+ void (QOPENGLF_APIENTRYP CompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
+ GL_APICALL void (QOPENGLF_APIENTRYP CompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
+ void (QOPENGLF_APIENTRYP CompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
+ void (QOPENGLF_APIENTRYP CompressedTexImage1D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
+ GL_APICALL void (QOPENGLF_APIENTRYP CompressedTexImage2D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
+ void (QOPENGLF_APIENTRYP CompressedTexImage3D)(GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
+ GL_APICALL void (QOPENGLF_APIENTRYP ActiveTexture)(GLenum texture);
+
+ // OpenGL 3.0
+ GL_APICALL void (QOPENGLF_APIENTRYP GenerateMipmap)(GLenum target);
+
+ // OpenGL 3.2
+ void (QOPENGLF_APIENTRYP TexImage3DMultisample)(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TexImage2DMultisample)(GLenum target, GLsizei samples, GLint internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+
+ // OpenGL 4.2
+ void (QOPENGLF_APIENTRYP TexStorage3D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth);
+ void (QOPENGLF_APIENTRYP TexStorage2D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height);
+ void (QOPENGLF_APIENTRYP TexStorage1D)(GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width);
+
+ // OpenGL 4.3
+ void (QOPENGLF_APIENTRYP TexStorage3DMultisample)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TexStorage2DMultisample)(GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations);
+ void (QOPENGLF_APIENTRYP TexBufferRange)(GLenum target, GLenum internalFormat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+ void (QOPENGLF_APIENTRYP TextureView)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers);
+};
+
+QT_END_NAMESPACE
+
+#undef Q_CALL_MEMBER_FUNCTION
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLTEXTUREHELPER_P_H
diff --git a/src/opengl/qopengltextureuploader.cpp b/src/opengl/qopengltextureuploader.cpp
new file mode 100644
index 0000000000..469ddc56c1
--- /dev/null
+++ b/src/opengl/qopengltextureuploader.cpp
@@ -0,0 +1,381 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "qopengltextureuploader_p.h"
+
+#include <qimage.h>
+#include <qmath.h>
+#include <qopenglfunctions.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
+
+#ifndef GL_RED
+#define GL_RED 0x1903
+#endif
+
+#ifndef GL_GREEN
+#define GL_GREEN 0x1904
+#endif
+
+#ifndef GL_BLUE
+#define GL_BLUE 0x1905
+#endif
+
+#ifndef GL_RGB10_A2
+#define GL_RGB10_A2 0x8059
+#endif
+
+#ifndef GL_RGBA16
+#define GL_RGBA16 0x805B
+#endif
+
+#ifndef GL_BGR
+#define GL_BGR 0x80E0
+#endif
+
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+
+#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
+#endif
+
+#ifndef GL_TEXTURE_SWIZZLE_R
+#define GL_TEXTURE_SWIZZLE_R 0x8E42
+#endif
+
+#ifndef GL_TEXTURE_SWIZZLE_G
+#define GL_TEXTURE_SWIZZLE_G 0x8E43
+#endif
+
+#ifndef GL_TEXTURE_SWIZZLE_B
+#define GL_TEXTURE_SWIZZLE_B 0x8E44
+#endif
+
+#ifndef GL_TEXTURE_SWIZZLE_A
+#define GL_TEXTURE_SWIZZLE_A 0x8E45
+#endif
+
+#ifndef GL_SRGB
+#define GL_SRGB 0x8C40
+#endif
+#ifndef GL_SRGB_ALPHA
+#define GL_SRGB_ALPHA 0x8C42
+#endif
+
+QT_BEGIN_NAMESPACE
+
+qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &image, QOpenGLTextureUploader::BindOptions options, QSize maxSize)
+{
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QOpenGLExtensions *funcs = static_cast<QOpenGLExtensions*>(context->functions());
+
+ QImage tx;
+ GLenum externalFormat;
+ GLenum internalFormat;
+ GLuint pixelType;
+ QImage::Format targetFormat = QImage::Format_Invalid;
+ const bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
+ const bool isOpenGLES3orBetter = context->isOpenGLES() && context->format().majorVersion() >= 3;
+ const bool sRgbBinding = (options & SRgbBindOption);
+ Q_ASSERT(isOpenGL12orBetter || context->isOpenGLES());
+ Q_ASSERT((options & (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption)) != (SRgbBindOption | UseRedForAlphaAndLuminanceBindOption));
+
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ if (isOpenGL12orBetter) {
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_INT_8_8_8_8_REV;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ // Without GL_UNSIGNED_INT_8_8_8_8_REV, BGRA only matches ARGB on little endian:
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::BGRATextureFormat) && !sRgbBinding) {
+ // The GL_EXT_texture_format_BGRA8888 extension requires the internal format to match the external.
+ externalFormat = internalFormat = GL_BGRA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else if (context->isOpenGLES() && context->hasExtension(QByteArrayLiteral("GL_APPLE_texture_format_BGRA8888"))) {
+ // Is only allowed as an external format like OpenGL.
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+#endif
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+#else
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_ALPHA);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, GL_RED);
+#endif
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ } else {
+ // No support for direct ARGB32 upload.
+ break;
+ }
+ targetFormat = image.format();
+ break;
+ case QImage::Format_BGR30:
+ case QImage::Format_A2BGR30_Premultiplied:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (isOpenGL12orBetter || isOpenGLES3orBetter) {
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_RGBA;
+ internalFormat = GL_RGB10_A2;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_RGB30:
+ case QImage::Format_A2RGB30_Premultiplied:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (isOpenGL12orBetter) {
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_BGRA;
+ internalFormat = GL_RGB10_A2;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
+ pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
+ externalFormat = GL_RGBA;
+ internalFormat = GL_RGB10_A2;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_RGB444:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB16:
+ if (isOpenGL12orBetter || context->isOpenGLES()) {
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_SHORT_5_6_5;
+ targetFormat = QImage::Format_RGB16;
+ }
+ break;
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB888:
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = QImage::Format_RGB888;
+ break;
+ case QImage::Format_BGR888:
+ if (isOpenGL12orBetter) {
+ externalFormat = GL_BGR;
+ internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = QImage::Format_BGR888;
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
+ externalFormat = internalFormat = GL_RGB;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = QImage::Format_BGR888;
+ }
+ break;
+ case QImage::Format_RGBX8888:
+ case QImage::Format_RGBA8888:
+ case QImage::Format_RGBA8888_Premultiplied:
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ break;
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64:
+ case QImage::Format_RGBA64_Premultiplied:
+ externalFormat = internalFormat = GL_RGBA;
+ if (isOpenGL12orBetter || (context->isOpenGLES() && context->format().majorVersion() >= 3))
+ internalFormat = GL_RGBA16;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ break;
+ case QImage::Format_Indexed8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_Alpha8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_ALPHA;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ALPHA);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_ZERO);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_ZERO);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ZERO);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_Grayscale8:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_LUMINANCE;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_BYTE;
+ targetFormat = image.format();
+ }
+ break;
+ case QImage::Format_Grayscale16:
+ if (sRgbBinding) {
+ // Always needs conversion
+ break;
+ } else if (options & UseRedForAlphaAndLuminanceBindOption) {
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ } else if (context->isOpenGLES() || context->format().profile() != QSurfaceFormat::CoreProfile) {
+ externalFormat = internalFormat = GL_LUMINANCE;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ } else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
+ funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, GL_ONE);
+ externalFormat = internalFormat = GL_RED;
+ pixelType = GL_UNSIGNED_SHORT;
+ targetFormat = image.format();
+ }
+ break;
+ default:
+ break;
+ }
+
+ // If no direct upload was detected above, convert to RGBA8888 and upload that
+ if (targetFormat == QImage::Format_Invalid) {
+ externalFormat = internalFormat = GL_RGBA;
+ pixelType = GL_UNSIGNED_BYTE;
+ if (!image.hasAlphaChannel())
+ targetFormat = QImage::Format_RGBX8888;
+ else
+ targetFormat = QImage::Format_RGBA8888;
+ }
+
+ if (options & PremultipliedAlphaBindOption) {
+ if (targetFormat == QImage::Format_ARGB32)
+ targetFormat = QImage::Format_ARGB32_Premultiplied;
+ else if (targetFormat == QImage::Format_RGBA8888)
+ targetFormat = QImage::Format_RGBA8888_Premultiplied;
+ else if (targetFormat == QImage::Format_RGBA64)
+ targetFormat = QImage::Format_RGBA64_Premultiplied;
+ } else {
+ if (targetFormat == QImage::Format_ARGB32_Premultiplied)
+ targetFormat = QImage::Format_ARGB32;
+ else if (targetFormat == QImage::Format_RGBA8888_Premultiplied)
+ targetFormat = QImage::Format_RGBA8888;
+ else if (targetFormat == QImage::Format_RGBA64_Premultiplied)
+ targetFormat = QImage::Format_RGBA64;
+ }
+
+ if (sRgbBinding) {
+ Q_ASSERT(internalFormat == GL_RGBA || internalFormat == GL_RGB);
+ if (image.hasAlphaChannel())
+ internalFormat = GL_SRGB_ALPHA;
+ else
+ internalFormat = GL_SRGB;
+ }
+
+ if (image.format() != targetFormat)
+ tx = image.convertToFormat(targetFormat);
+ else
+ tx = image;
+
+ QSize newSize = tx.size();
+ if (!maxSize.isEmpty())
+ newSize = newSize.boundedTo(maxSize);
+ if (options & PowerOfTwoBindOption) {
+ newSize.setWidth(qNextPowerOfTwo(newSize.width() - 1));
+ newSize.setHeight(qNextPowerOfTwo(newSize.height() - 1));
+ }
+
+ if (newSize != tx.size())
+ tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ // Handle cases where the QImage is actually a sub image of its image data:
+ qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2;
+ if (tx.bytesPerLine() != naturalBpl)
+ tx = tx.copy(tx.rect());
+
+ funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits());
+
+ qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8;
+
+ return cost;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qgraphicsshadereffect_p.h b/src/opengl/qopengltextureuploader_p.h
index 218caa2936..cea6d97658 100644
--- a/src/opengl/qgraphicsshadereffect_p.h
+++ b/src/opengl/qopengltextureuploader_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
@@ -37,9 +37,6 @@
**
****************************************************************************/
-#ifndef QGRAPHICSSHADEREFFECT_P_H
-#define QGRAPHICSSHADEREFFECT_P_H
-
//
// W A R N I N G
// -------------
@@ -51,40 +48,37 @@
// We mean it.
//
-#include <QtWidgets/qgraphicseffect.h>
+#ifndef QOPENGLTEXTUREUPLOADER_P_H
+#define QOPENGLTEXTUREUPLOADER_P_H
+#include <QtCore/qsize.h>
#include <QtOpenGL/qtopenglglobal.h>
-
-QT_REQUIRE_CONFIG(graphicseffect);
+#include <QtGui/private/qopenglcontext_p.h>
QT_BEGIN_NAMESPACE
-class QGLShaderProgram;
-class QGLCustomShaderEffectStage;
-class QGraphicsShaderEffectPrivate;
+class QImage;
-class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect
+class Q_OPENGL_EXPORT QOpenGLTextureUploader
{
- Q_OBJECT
public:
- QGraphicsShaderEffect(QObject *parent = nullptr);
- virtual ~QGraphicsShaderEffect();
-
- QByteArray pixelShaderFragment() const;
- void setPixelShaderFragment(const QByteArray& code);
+ enum BindOption {
+ NoBindOption = 0x0000,
+ PremultipliedAlphaBindOption = 0x0001,
+ UseRedForAlphaAndLuminanceBindOption = 0x0002,
+ SRgbBindOption = 0x0004,
+ PowerOfTwoBindOption = 0x0008
+ };
+ Q_DECLARE_FLAGS(BindOptions, BindOption)
+ Q_FLAGS(BindOptions)
-protected:
- void draw(QPainter *painter) override;
- void setUniformsDirty();
- virtual void setUniforms(QGLShaderProgram *program);
+ static qsizetype textureImage(GLenum target, const QImage &image, BindOptions options, QSize maxSize = QSize());
-private:
- Q_DECLARE_PRIVATE(QGraphicsShaderEffect)
- Q_DISABLE_COPY_MOVE(QGraphicsShaderEffect)
-
- friend class QGLCustomShaderEffectStage;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTextureUploader::BindOptions)
+
QT_END_NAMESPACE
-#endif // QGRAPHICSSHADEREFFECT_P_H
+#endif
+
diff --git a/src/opengl/qopengltimerquery.cpp b/src/opengl/qopengltimerquery.cpp
new file mode 100644
index 0000000000..44955d48fc
--- /dev/null
+++ b/src/opengl/qopengltimerquery.cpp
@@ -0,0 +1,880 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 "qopengltimerquery.h"
+
+#include "qopenglqueryhelper_p.h"
+#include <QtCore/private/qobject_p.h>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFunctions>
+
+QT_BEGIN_NAMESPACE
+
+// Helper class used as fallback if OpenGL <3.3 is being used with EXT_timer_query
+class QExtTimerQueryHelper
+{
+public:
+ QExtTimerQueryHelper(QOpenGLContext *context)
+ {
+ Q_ASSERT(context);
+ GetQueryObjectui64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64EXT *)>(context->getProcAddress("glGetQueryObjectui64vEXT"));
+ GetQueryObjecti64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64EXT *)>(context->getProcAddress("glGetQueryObjecti64vEXT"));
+ }
+
+ inline void glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
+ {
+ GetQueryObjectui64vEXT(id, pname, params);
+ }
+
+ inline void glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
+ {
+ GetQueryObjecti64vEXT(id, pname, params);
+ }
+
+private:
+ void (QOPENGLF_APIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT *params);
+ void (QOPENGLF_APIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT *params);
+};
+
+class QOpenGLTimerQueryPrivate : public QObjectPrivate
+{
+public:
+ QOpenGLTimerQueryPrivate()
+ : QObjectPrivate(),
+ context(nullptr),
+ ext(nullptr),
+ timeInterval(0),
+ timer(0)
+ {
+ }
+
+ ~QOpenGLTimerQueryPrivate()
+ {
+ delete core;
+ delete ext;
+ }
+
+ bool create();
+ void destroy();
+ void begin();
+ void end();
+ GLuint64 waitForTimeStamp() const;
+ void recordTimestamp();
+ bool isResultAvailable() const;
+ GLuint64 result() const;
+
+ // There are several cases we must handle:
+ // OpenGL >=3.3 includes timer queries as a core feature
+ // ARB_timer_query has same functionality as above. Requires OpenGL 3.2
+ // EXT_timer_query offers limited support. Can be used with OpenGL >=1.5
+ //
+ // Note that some implementations (OS X) provide OpenGL 3.2 but do not expose the
+ // ARB_timer_query extension. In such situations we must also be able to handle
+ // using the EXT_timer_query extension with any version of OpenGL.
+ //
+ // OpenGL 1.5 or above contains the generic query API and OpenGL 3.3 and
+ // ARB_timer_query provide the 64-bit query API. These are wrapped by
+ // QOpenGLQueryHelper. All we need to handle in addition is the EXT_timer_query
+ // case and to take care not to call the Core/ARB functions when we only
+ // have EXT_timer_query available.
+ QOpenGLContext *context;
+ QOpenGLQueryHelper *core;
+ QExtTimerQueryHelper *ext;
+ mutable GLuint64 timeInterval;
+ GLuint timer;
+};
+
+bool QOpenGLTimerQueryPrivate::create()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ if (timer && context == ctx)
+ return true;
+
+ context = ctx;
+ if (!context) {
+ qWarning("A current OpenGL context is required to create timer query objects");
+ return false;
+ }
+
+ if (context->isOpenGLES()) {
+ qWarning("QOpenGLTimerQuery: Not supported on OpenGL ES");
+ return false;
+ }
+
+ // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query
+ core = new QOpenGLQueryHelper(context);
+
+ // Check to see if we also need to resolve the functions for EXT_timer_query
+ QSurfaceFormat f = context->format();
+ if (f.version() <= qMakePair<int, int>(3, 2)
+ && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
+ && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
+ ext = new QExtTimerQueryHelper(context);
+ } else if (f.version() <= qMakePair<int, int>(3, 2)
+ && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
+ && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
+ qWarning("QOpenGLTimerQuery requires one of:\n"
+ " OpenGL 3.3 or newer,\n"
+ " OpenGL 3.2 and the ARB_timer_query extension\n"
+ " or the EXT_timer query extension");
+ return false;
+ }
+
+ core->glGenQueries(1, &timer);
+ return (timer != 0);
+}
+
+void QOpenGLTimerQueryPrivate::destroy()
+{
+ if (!timer)
+ return;
+
+ core->glDeleteQueries(1, &timer);
+ timer = 0;
+ context = nullptr;
+}
+
+// GL_TIME_ELAPSED_EXT is not defined on OS X 10.6
+#if !defined(GL_TIME_ELAPSED_EXT)
+#define GL_TIME_ELAPSED_EXT 0x88BF
+#endif
+
+// GL_TIME_ELAPSED is not defined on OS X 10.7 or 10.8 yet
+#if !defined(GL_TIME_ELAPSED)
+#define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT
+#endif
+
+void QOpenGLTimerQueryPrivate::begin()
+{
+ core->glBeginQuery(GL_TIME_ELAPSED, timer);
+}
+
+void QOpenGLTimerQueryPrivate::end()
+{
+ core->glEndQuery(GL_TIME_ELAPSED);
+}
+
+void QOpenGLTimerQueryPrivate::recordTimestamp()
+{
+ // Don't call glQueryCounter if we only have EXT_timer_query
+#if defined(GL_TIMESTAMP)
+ if (!ext)
+ core->glQueryCounter(timer, GL_TIMESTAMP);
+ else
+ qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
+#else
+ qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
+#endif
+}
+
+GLuint64 QOpenGLTimerQueryPrivate::waitForTimeStamp() const
+{
+ GLint64 tmp = 0;
+#if defined(GL_TIMESTAMP)
+ if (!ext)
+ core->glGetInteger64v(GL_TIMESTAMP, &tmp);
+ else
+ qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
+#else
+ qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
+#endif
+ GLuint64 timestamp(tmp);
+ return timestamp;
+}
+
+bool QOpenGLTimerQueryPrivate::isResultAvailable() const
+{
+ GLuint available = GL_FALSE;
+ core->glGetQueryObjectuiv(timer, GL_QUERY_RESULT_AVAILABLE, &available);
+ return available;
+}
+
+GLuint64 QOpenGLTimerQueryPrivate::result() const
+{
+ if (!ext)
+ core->glGetQueryObjectui64v(timer, GL_QUERY_RESULT, &timeInterval);
+ else
+ ext->glGetQueryObjectui64vEXT(timer, GL_QUERY_RESULT, &timeInterval);
+ return timeInterval;
+}
+
+/*!
+ \class QOpenGLTimerQuery
+ \brief The QOpenGLTimerQuery class wraps an OpenGL timer query object.
+ \inmodule QtOpenGL
+ \since 5.1
+ \ingroup painting-3D
+
+ OpenGL timer query objects are OpenGL managed resources to measure the
+ execution times of sequences of OpenGL commands on the GPU.
+
+ OpenGL offers various levels of support for timer queries, depending on
+ the version of OpenGL you have and the presence of the ARB_timer_query or
+ EXT_timer_query extensions. The support can be summarized as:
+
+ \list
+ \li OpenGL >=3.3 offers full support for all timer query functionality.
+ \li OpenGL 3.2 with the ARB_timer_query extension offers full support
+ for all timer query functionality.
+ \li OpenGL <=3.2 with the EXT_timer_query extension offers limited support
+ in that the timestamp of the GPU cannot be queried. Places where this
+ impacts functions provided by Qt classes will be highlighted in the
+ function documentation.
+ \li OpenGL ES 2 (and OpenGL ES 3) do not provide any support for OpenGL
+ timer queries.
+ \endlist
+
+ OpenGL represents time with a granularity of 1 nanosecond (1e-9 seconds). As a
+ consequence of this, 32-bit integers would only give a total possible duration
+ of approximately 4 seconds, which would not be difficult to exceed in poorly
+ performing or lengthy operations. OpenGL therefore uses 64 bit integer types
+ to represent times. A GLuint64 variable has enough width to contain a duration
+ of hundreds of years, which is plenty for real-time rendering needs.
+
+ As with the other Qt OpenGL classes, QOpenGLTimerQuery has a create()
+ function to create the underlying OpenGL object. This is to allow the developer to
+ ensure that there is a valid current OpenGL context at the time.
+
+ Once created, timer queries can be issued in one of several ways. The simplest
+ method is to delimit a block of commands with calls to begin() and end(). This
+ instructs OpenGL to measure the time taken from completing all commands issued
+ prior to begin() until the completion of all commands issued prior to end().
+
+ At the end of a frame we can retrieve the results by calling waitForResult().
+ As this function's name implies, it blocks CPU execution until OpenGL notifies
+ that the timer query result is available. To avoid blocking, you can check
+ if the query result is available by calling isResultAvailable(). Note that
+ modern GPUs are deeply pipelined and query results may not become available for
+ between 1-5 frames after they were issued.
+
+ Note that OpenGL does not permit nesting or interleaving of multiple timer queries
+ using begin() and end(). Using multiple timer queries and recordTimestamp() avoids
+ this limitation. When using recordTimestamp() the result can be obtained at
+ some later time using isResultAvailable() and waitForResult(). Qt provides the
+ convenience class QOpenGLTimeMonitor that helps with using multiple query objects.
+
+ \sa QOpenGLTimeMonitor
+*/
+
+/*!
+ Creates a QOpenGLTimerQuery instance with the given \a parent. You must call create()
+ with a valid OpenGL context before using.
+*/
+QOpenGLTimerQuery::QOpenGLTimerQuery(QObject *parent)
+ : QObject(*new QOpenGLTimerQueryPrivate, parent)
+{
+}
+
+/*!
+ Destroys the QOpenGLTimerQuery and the underlying OpenGL resource.
+*/
+QOpenGLTimerQuery::~QOpenGLTimerQuery()
+{
+ QOpenGLContext* ctx = QOpenGLContext::currentContext();
+
+ Q_D(QOpenGLTimerQuery);
+ QOpenGLContext *oldContext = nullptr;
+ if (d->context != ctx) {
+ oldContext = ctx;
+ if (d->context->makeCurrent(oldContext->surface())) {
+ ctx = d->context;
+ } else {
+ qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to make query objects's context current");
+ ctx = nullptr;
+ }
+ }
+
+ if (ctx)
+ destroy();
+
+ if (oldContext) {
+ if (!oldContext->makeCurrent(oldContext->surface()))
+ qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to restore current context");
+ }
+}
+
+/*!
+ Creates the underlying OpenGL timer query object. There must be a valid OpenGL context
+ that supports query objects current for this function to succeed.
+
+ Returns \c true if the OpenGL timer query object was successfully created.
+*/
+bool QOpenGLTimerQuery::create()
+{
+ Q_D(QOpenGLTimerQuery);
+ return d->create();
+}
+
+/*!
+ Destroys the underlying OpenGL timer query object. The context that was current when
+ create() was called must be current when calling this function.
+*/
+void QOpenGLTimerQuery::destroy()
+{
+ Q_D(QOpenGLTimerQuery);
+ d->destroy();
+}
+
+/*!
+ Returns \c true if the underlying OpenGL query object has been created. If this
+ returns \c true and the associated OpenGL context is current, then you are able to issue
+ queries with this object.
+*/
+bool QOpenGLTimerQuery::isCreated() const
+{
+ Q_D(const QOpenGLTimerQuery);
+ return (d->timer != 0);
+}
+
+/*!
+ Returns the id of the underlying OpenGL query object.
+*/
+GLuint QOpenGLTimerQuery::objectId() const
+{
+ Q_D(const QOpenGLTimerQuery);
+ return d->timer;
+}
+
+/*!
+ Marks the start point in the OpenGL command queue for a sequence of commands to
+ be timed by this query object.
+
+ This is useful for simple use-cases. Usually it is better to use recordTimestamp().
+
+ \sa end(), isResultAvailable(), waitForResult(), recordTimestamp()
+*/
+void QOpenGLTimerQuery::begin()
+{
+ Q_D(QOpenGLTimerQuery);
+ d->begin();
+}
+
+/*!
+ Marks the end point in the OpenGL command queue for a sequence of commands to
+ be timed by this query object.
+
+ This is useful for simple use-cases. Usually it is better to use recordTimestamp().
+
+ \sa begin(), isResultAvailable(), waitForResult(), recordTimestamp()
+*/
+void QOpenGLTimerQuery::end()
+{
+ Q_D(QOpenGLTimerQuery);
+ d->end();
+}
+
+/*!
+ Places a marker in the OpenGL command queue for the GPU to record the timestamp
+ when this marker is reached by the GPU. This function is non-blocking and the
+ result will become available at some later time.
+
+ The availability of the result can be checked with isResultAvailable(). The result
+ can be fetched with waitForResult() which will block if the result is not yet
+ available.
+
+ \sa waitForResult(), isResultAvailable(), begin(), end()
+*/
+void QOpenGLTimerQuery::recordTimestamp()
+{
+ Q_D(QOpenGLTimerQuery);
+ return d->recordTimestamp();
+}
+
+/*!
+ Returns the current timestamp of the GPU when all previously issued OpenGL
+ commands have been received but not necessarily executed by the GPU.
+
+ This function blocks until the result is returned.
+
+ \sa recordTimestamp()
+*/
+GLuint64 QOpenGLTimerQuery::waitForTimestamp() const
+{
+ Q_D(const QOpenGLTimerQuery);
+ return d->waitForTimeStamp();
+}
+
+/*!
+ Returns \c true if the OpenGL timer query result is available.
+
+ This function is non-blocking and ideally should be used to check for the
+ availability of the query result before calling waitForResult().
+
+ \sa waitForResult()
+*/
+bool QOpenGLTimerQuery::isResultAvailable() const
+{
+ Q_D(const QOpenGLTimerQuery);
+ return d->isResultAvailable();
+}
+
+/*!
+ Returns the result of the OpenGL timer query.
+
+ This function will block until the result is made available by OpenGL. It is
+ recommended to call isResultAvailable() to ensure that the result is available
+ to avoid unnecessary blocking and stalling.
+
+ \sa isResultAvailable()
+*/
+GLuint64 QOpenGLTimerQuery::waitForResult() const
+{
+ Q_D(const QOpenGLTimerQuery);
+ return d->result();
+}
+
+
+class QOpenGLTimeMonitorPrivate : public QObjectPrivate
+{
+public:
+ QOpenGLTimeMonitorPrivate()
+ : QObjectPrivate(),
+ timers(),
+ timeSamples(),
+ context(nullptr),
+ core(nullptr),
+ ext(nullptr),
+ requestedSampleCount(2),
+ currentSample(-1),
+ timerQueryActive(false)
+ {
+ }
+
+ ~QOpenGLTimeMonitorPrivate()
+ {
+ delete core;
+ delete ext;
+ }
+
+ bool create();
+ void destroy();
+ void recordSample();
+ bool isResultAvailable() const;
+ QVector<GLuint64> samples() const;
+ QVector<GLuint64> intervals() const;
+ void reset();
+
+ QVector<GLuint> timers;
+ mutable QVector<GLuint64> timeSamples;
+
+ QOpenGLContext *context;
+ QOpenGLQueryHelper *core;
+ QExtTimerQueryHelper *ext;
+
+ int requestedSampleCount;
+ int currentSample;
+ mutable bool timerQueryActive;
+};
+
+bool QOpenGLTimeMonitorPrivate::create()
+{
+ if (!timers.isEmpty() && timers.at(0) != 0 && timers.size() == requestedSampleCount)
+ return true;
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (context && context != ctx) {
+ qWarning("QTimeMonitor: Attempting to use different OpenGL context to recreate timers.\n"
+ "Please call destroy() first or use the same context to previously create");
+ return false;
+ }
+
+ context = ctx;
+ if (!context) {
+ qWarning("A current OpenGL context is required to create timer query objects");
+ return false;
+ }
+
+ // Resize the vectors that hold the timers and the recorded samples
+ timers.resize(requestedSampleCount);
+ timeSamples.resize(requestedSampleCount);
+
+ // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query
+ core = new QOpenGLQueryHelper(context);
+
+ // Check to see if we also need to resolve the functions for EXT_timer_query
+ QSurfaceFormat f = context->format();
+ if (f.version() <= qMakePair<int, int>(3, 2)
+ && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
+ && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
+ ext = new QExtTimerQueryHelper(context);
+ } else if (f.version() <= qMakePair<int, int>(3, 2)
+ && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
+ && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
+ qWarning("QOpenGLTimeMonitor requires one of:\n"
+ " OpenGL 3.3 or newer,\n"
+ " OpenGL 3.2 and the ARB_timer_query extension\n"
+ " or the EXT_timer query extension");
+ return false;
+ }
+
+ core->glGenQueries(requestedSampleCount, timers.data());
+ return (timers.at(0) != 0);
+}
+
+void QOpenGLTimeMonitorPrivate::destroy()
+{
+ if (timers.isEmpty() || timers.at(0) == 0)
+ return;
+
+ core->glDeleteQueries(timers.size(), timers.data());
+ timers.clear();
+ delete core;
+ core = nullptr;
+ delete ext;
+ ext = nullptr;
+ context = nullptr;
+}
+
+void QOpenGLTimeMonitorPrivate::recordSample()
+{
+ // Use glQueryCounter() and GL_TIMESTAMP where available.
+ // Otherwise, simulate it with glBeginQuery()/glEndQuery()
+ if (!ext) {
+#if defined(GL_TIMESTAMP)
+ core->glQueryCounter(timers.at(++currentSample), GL_TIMESTAMP);
+#endif
+ } else {
+ if (currentSample == -1) {
+ core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample));
+ timerQueryActive = true;
+ } else if (currentSample < timers.size() - 1) {
+ core->glEndQuery(GL_TIME_ELAPSED_EXT);
+ core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample));
+ } else {
+ if (timerQueryActive) {
+ core->glEndQuery(GL_TIME_ELAPSED_EXT);
+ timerQueryActive = false;
+ }
+ }
+ }
+}
+
+bool QOpenGLTimeMonitorPrivate::isResultAvailable() const
+{
+ // The OpenGL spec says that if a query result is ready then the results of all queries
+ // of the same type issued before it must also be ready. Therefore we only need to check
+ // the availability of the result for the last issued query
+ GLuint available = GL_FALSE;
+ core->glGetQueryObjectuiv(timers.at(currentSample), GL_QUERY_RESULT_AVAILABLE, &available);
+ return available;
+}
+
+QVector<GLuint64> QOpenGLTimeMonitorPrivate::samples() const
+{
+ // For the Core and ARB options just ask for the timestamp for each timer query.
+ // For the EXT implementation we cannot obtain timestamps so we defer any result
+ // collection to the intervals() function
+ if (!ext) {
+ for (int i = 0; i <= currentSample; ++i)
+ core->glGetQueryObjectui64v(timers.at(i), GL_QUERY_RESULT, &timeSamples[i]);
+ } else {
+ qWarning("QOpenGLTimeMonitor::samples() requires OpenGL >=3.3\n"
+ "or OpenGL 3.2 and GL_ARB_timer_query");
+ }
+ return timeSamples;
+}
+
+QVector<GLuint64> QOpenGLTimeMonitorPrivate::intervals() const
+{
+ QVector<GLuint64> intervals(timers.size() - 1);
+ if (!ext) {
+ // Obtain the timestamp samples and calculate the interval durations
+ const QVector<GLuint64> timeStamps = samples();
+ for (int i = 0; i < intervals.size(); ++i)
+ intervals[i] = timeStamps[i+1] - timeStamps[i];
+ } else {
+ // Stop the last timer if needed
+ if (timerQueryActive) {
+ core->glEndQuery(GL_TIME_ELAPSED_EXT);
+ timerQueryActive = false;
+ }
+
+ // Obtain the results from all timers apart from the redundant last one. In this
+ // case the results actually are the intervals not timestamps
+ for (int i = 0; i < currentSample; ++i)
+ ext->glGetQueryObjectui64vEXT(timers.at(i), GL_QUERY_RESULT, &intervals[i]);
+ }
+
+ return intervals;
+}
+
+void QOpenGLTimeMonitorPrivate::reset()
+{
+ currentSample = -1;
+ timeSamples.fill(0);
+}
+
+
+/*!
+ \class QOpenGLTimeMonitor
+ \brief The QOpenGLTimeMonitor class wraps a sequence of OpenGL timer query objects.
+ \inmodule QtOpenGL
+ \since 5.1
+ \ingroup painting-3D
+
+ The QOpenGLTimeMonitor class is a convenience wrapper around a collection of OpenGL
+ timer query objects used to measure intervals of time on the GPU to the level of
+ granularity required by your rendering application.
+
+ The OpenGL timer queries objects are queried in sequence to record the GPU
+ timestamps at positions of interest in your rendering code. Once the results for
+ all issues timer queries become available, the results can be fetched and
+ QOpenGLTimerMonitor will calculate the recorded time intervals for you.
+
+ The typical use case of this class is to either profile your application's rendering
+ algorithms or to adjust those algorithms in real-time for dynamic performance/quality
+ balancing.
+
+ Prior to using QOpenGLTimeMonitor in your rendering function you should set the
+ required number of sample points that you wish to record by calling setSamples(). Note
+ that measuring N sample points will produce N-1 time intervals. Once you have set the
+ number of sample points, call the create() function with a valid current OpenGL context
+ to create the necessary query timer objects. These steps are usually performed just
+ once in an initialization function.
+
+ Use the recordSample() function to delimit blocks of code containing OpenGL commands
+ that you wish to time. You can check availability of the resulting time
+ samples and time intervals with isResultAvailable(). The calculated time intervals and
+ the raw timestamp samples can be retrieved with the blocking waitForIntervals() and
+ waitForSamples() functions respectively.
+
+ After retrieving the results and before starting a new round of taking samples
+ (for example, in the next frame) be sure to call the reset() function which will clear
+ the cached results and reset the timer index back to the first timer object.
+
+ \sa QOpenGLTimerQuery
+*/
+
+/*!
+ Creates a QOpenGLTimeMonitor instance with the given \a parent. You must call create()
+ with a valid OpenGL context before using.
+
+ \sa setSampleCount(), create()
+*/
+QOpenGLTimeMonitor::QOpenGLTimeMonitor(QObject *parent)
+ : QObject(*new QOpenGLTimeMonitorPrivate, parent)
+{
+}
+
+/*!
+ Destroys the QOpenGLTimeMonitor and any underlying OpenGL resources.
+*/
+QOpenGLTimeMonitor::~QOpenGLTimeMonitor()
+{
+ QOpenGLContext* ctx = QOpenGLContext::currentContext();
+
+ Q_D(QOpenGLTimeMonitor);
+ QOpenGLContext *oldContext = nullptr;
+ if (d->context != ctx) {
+ oldContext = ctx;
+ if (d->context->makeCurrent(oldContext->surface())) {
+ ctx = d->context;
+ } else {
+ qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to make time monitor's context current");
+ ctx = nullptr;
+ }
+ }
+
+ if (ctx)
+ destroy();
+
+ if (oldContext) {
+ if (!oldContext->makeCurrent(oldContext->surface()))
+ qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to restore current context");
+ }
+}
+
+/*!
+ Sets the number of sample points to \a sampleCount. After setting the number
+ of samples with this function, you must call create() to instantiate the underlying
+ OpenGL timer query objects.
+
+ The new \a sampleCount must be at least 2.
+
+ \sa sampleCount(), create(), recordSample()
+*/
+void QOpenGLTimeMonitor::setSampleCount(int sampleCount)
+{
+ // We need at least 2 samples to get an interval
+ if (sampleCount < 2)
+ return;
+ Q_D(QOpenGLTimeMonitor);
+ d->requestedSampleCount = sampleCount;
+}
+
+/*!
+ Returns the number of sample points that have been requested with
+ setSampleCount(). If create was successfully called following setSampleCount(),
+ then the value returned will be the actual number of sample points
+ that can be used.
+
+ The default value for sample count is 2, leading to the measurement of a
+ single interval.
+
+ \sa setSampleCount()
+*/
+int QOpenGLTimeMonitor::sampleCount() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return d->requestedSampleCount;
+}
+
+/*!
+ Instantiate sampleCount() OpenGL timer query objects that will be used
+ to track the amount of time taken to execute OpenGL commands between
+ successive calls to recordSample().
+
+ Returns \c true if the OpenGL timer query objects could be created.
+
+ \sa destroy(), setSampleCount(), recordSample()
+*/
+bool QOpenGLTimeMonitor::create()
+{
+ Q_D(QOpenGLTimeMonitor);
+ return d->create();
+}
+
+/*!
+ Destroys any OpenGL timer query objects used within this instance.
+
+ \sa create()
+*/
+void QOpenGLTimeMonitor::destroy()
+{
+ Q_D(QOpenGLTimeMonitor);
+ d->destroy();
+}
+
+/*!
+ Returns \c true if the underlying OpenGL query objects have been created. If this
+ returns \c true and the associated OpenGL context is current, then you are able to record
+ time samples with this object.
+*/
+bool QOpenGLTimeMonitor::isCreated() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return (!d->timers.isEmpty() && d->timers.at(0) != 0);
+}
+
+/*!
+ Returns a QVector containing the object Ids of the OpenGL timer query objects.
+*/
+QVector<GLuint> QOpenGLTimeMonitor::objectIds() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return d->timers;
+}
+
+/*!
+ Issues an OpenGL timer query at this point in the OpenGL command queue. Calling this
+ function in a sequence in your application's rendering function, will build up
+ details of the GPU time taken to execute the OpenGL commands between successive
+ calls to this function.
+
+ \sa setSampleCount(), isResultAvailable(), waitForSamples(), waitForIntervals()
+*/
+int QOpenGLTimeMonitor::recordSample()
+{
+ Q_D(QOpenGLTimeMonitor);
+ d->recordSample();
+ return d->currentSample;
+}
+
+/*!
+ Returns \c true if the OpenGL timer query results are available.
+
+ \sa waitForSamples(), waitForIntervals()
+*/
+bool QOpenGLTimeMonitor::isResultAvailable() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return d->isResultAvailable();
+}
+
+/*!
+ Returns a QVector containing the GPU timestamps taken with recordSample().
+
+ This function will block until OpenGL indicates the results are available. It
+ is recommended to check the availability of the result prior to calling this
+ function with isResultAvailable().
+
+ \note This function only works on systems that have OpenGL >=3.3 or the
+ ARB_timer_query extension. See QOpenGLTimerQuery for more details.
+
+ \sa waitForIntervals(), isResultAvailable()
+*/
+QVector<GLuint64> QOpenGLTimeMonitor::waitForSamples() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return d->samples();
+}
+
+/*!
+ Returns a QVector containing the time intervals delimited by the calls to
+ recordSample(). The resulting vector will contain one fewer element as
+ this represents the intervening intervals rather than the actual timestamp
+ samples.
+
+ This function will block until OpenGL indicates the results are available. It
+ is recommended to check the availability of the result prior to calling this
+ function with isResultAvailable().
+
+ \sa waitForSamples(), isResultAvailable()
+*/
+QVector<GLuint64> QOpenGLTimeMonitor::waitForIntervals() const
+{
+ Q_D(const QOpenGLTimeMonitor);
+ return d->intervals();
+}
+
+/*!
+ Resets the time monitor ready for use in another frame of rendering. Call
+ this once you have obtained the previous results and before calling
+ recordSample() for the first time on the next frame.
+
+ \sa recordSample()
+*/
+void QOpenGLTimeMonitor::reset()
+{
+ Q_D(QOpenGLTimeMonitor);
+ d->reset();
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopengltimerquery.h b/src/opengl/qopengltimerquery.h
new file mode 100644
index 0000000000..a779240108
--- /dev/null
+++ b/src/opengl/qopengltimerquery.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
+** 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 QOPENGLTIMERQUERY_H
+#define QOPENGLTIMERQUERY_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2)
+
+#include <QtCore/QObject>
+#include <QtGui/qopengl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLTimerQueryPrivate;
+
+class Q_OPENGL_EXPORT QOpenGLTimerQuery : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QOpenGLTimerQuery(QObject *parent = nullptr);
+ ~QOpenGLTimerQuery();
+
+ bool create();
+ void destroy();
+ bool isCreated() const;
+ GLuint objectId() const;
+
+ void begin();
+ void end();
+ GLuint64 waitForTimestamp() const;
+ void recordTimestamp();
+ bool isResultAvailable() const;
+ GLuint64 waitForResult() const;
+
+private:
+ Q_DECLARE_PRIVATE(QOpenGLTimerQuery)
+ Q_DISABLE_COPY(QOpenGLTimerQuery)
+};
+
+
+class QOpenGLTimeMonitorPrivate;
+
+class Q_OPENGL_EXPORT QOpenGLTimeMonitor : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit QOpenGLTimeMonitor(QObject *parent = nullptr);
+ ~QOpenGLTimeMonitor();
+
+ void setSampleCount(int sampleCount);
+ int sampleCount() const;
+
+ bool create();
+ void destroy();
+ bool isCreated() const;
+ QVector<GLuint> objectIds() const;
+
+ int recordSample();
+
+ bool isResultAvailable() const;
+
+ QVector<GLuint64> waitForSamples() const;
+ QVector<GLuint64> waitForIntervals() const;
+
+ void reset();
+
+private:
+ Q_DECLARE_PRIVATE(QOpenGLTimeMonitor)
+ Q_DISABLE_COPY(QOpenGLTimeMonitor)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_OPENGL
+
+#endif // QOPENGLTIMERQUERY_H
diff --git a/src/opengl/qopenglwidget.cpp b/src/opengl/qopenglwidget.cpp
new file mode 100644
index 0000000000..b334ba867b
--- /dev/null
+++ b/src/opengl/qopenglwidget.cpp
@@ -0,0 +1,1473 @@
+/****************************************************************************
+**
+** 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 "qopenglwidget.h"
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOffscreenSurface>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QWindow>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
+#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtOpenGL/QOpenGLPaintDevice>
+
+#include <QtGui/private/qguiapplication_p.h>
+#include <QtGui/private/qopenglextensions_p.h>
+#include <QtGui/private/qfont_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtOpenGL/private/qopenglpaintdevice_p.h>
+
+#include <QtWidgets/private/qwidget_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLWidget
+ \inmodule QtOpenGL
+ \since 5.4
+
+ \brief The QOpenGLWidget class is a widget for rendering OpenGL graphics.
+
+ QOpenGLWidget provides functionality for displaying OpenGL graphics
+ integrated into a Qt application. It is very simple to use: Make
+ your class inherit from it and use the subclass like any other
+ QWidget, except that you have the choice between using QPainter and
+ standard OpenGL rendering commands.
+
+ QOpenGLWidget provides three convenient virtual functions that you
+ can reimplement in your subclass to perform the typical OpenGL
+ tasks:
+
+ \list
+ \li paintGL() - Renders the OpenGL scene. Gets called whenever the widget
+ needs to be updated.
+ \li resizeGL() - Sets up the OpenGL viewport, projection, etc. Gets
+ called whenever the widget has been resized (and also when it
+ is shown for the first time because all newly created widgets get a
+ resize event automatically).
+ \li initializeGL() - Sets up the OpenGL resources and state. Gets called
+ once before the first time resizeGL() or paintGL() is called.
+ \endlist
+
+ If you need to trigger a repaint from places other than paintGL() (a
+ typical example is when using \l{QTimer}{timers} to animate scenes),
+ you should call the widget's update() function to schedule an update.
+
+ Your widget's OpenGL rendering context is made current when
+ paintGL(), resizeGL(), or initializeGL() is called. If you need to
+ call the standard OpenGL API functions from other places (e.g. in
+ your widget's constructor or in your own paint functions), you
+ must call makeCurrent() first.
+
+ All rendering happens into an OpenGL framebuffer
+ object. makeCurrent() ensure that it is bound in the context. Keep
+ this in mind when creating and binding additional framebuffer
+ objects in the rendering code in paintGL(). Never re-bind the
+ framebuffer with ID 0. Instead, call defaultFramebufferObject() to
+ get the ID that should be bound.
+
+ QOpenGLWidget allows using different OpenGL versions and profiles
+ when the platform supports it. Just set the requested format via
+ setFormat(). Keep in mind however that having multiple QOpenGLWidget
+ instances in the same window requires that they all use the same
+ format, or at least formats that do not make the contexts
+ non-sharable. To overcome this issue, prefer using
+ QSurfaceFormat::setDefaultFormat() instead of setFormat().
+
+ \note Calling QSurfaceFormat::setDefaultFormat() before constructing
+ the QApplication instance is mandatory on some platforms (for example,
+ \macos) when an OpenGL core profile context is requested. This is to
+ ensure that resource sharing between contexts stays functional as all
+ internal contexts are created using the correct version and profile.
+
+ \section1 Painting Techniques
+
+ As described above, subclass QOpenGLWidget to render pure 3D content in the
+ following way:
+
+ \list
+
+ \li Reimplement the initializeGL() and resizeGL() functions to
+ set up the OpenGL state and provide a perspective transformation.
+
+ \li Reimplement paintGL() to paint the 3D scene, calling only
+ OpenGL functions.
+
+ \endlist
+
+ It is also possible to draw 2D graphics onto a QOpenGLWidget subclass using QPainter:
+
+ \list
+
+ \li In paintGL(), instead of issuing OpenGL commands, construct a QPainter
+ object for use on the widget.
+
+ \li Draw primitives using QPainter's member functions.
+
+ \li Direct OpenGL commands can still be issued. However, you must make sure
+ these are enclosed by a call to the painter's beginNativePainting() and
+ endNativePainting().
+
+ \endlist
+
+ When performing drawing using QPainter only, it is also possible to perform
+ the painting like it is done for ordinary widgets: by reimplementing paintEvent().
+
+ \list
+
+ \li Reimplement the paintEvent() function.
+
+ \li Construct a QPainter object targeting the widget. Either pass the widget to the
+ constructor or the QPainter::begin() function.
+
+ \li Draw primitives using QPainter's member functions.
+
+ \li Painting finishes then the QPainter instance is destroyed. Alternatively,
+ call QPainter::end() explicitly.
+
+ \endlist
+
+ \section1 OpenGL Function Calls, Headers and QOpenGLFunctions
+
+ When making OpenGL function calls, it is strongly recommended to avoid calling
+ the functions directly. Instead, prefer using QOpenGLFunctions (when making
+ portable applications) or the versioned variants (for example,
+ QOpenGLFunctions_3_2_Core and similar, when targeting modern, desktop-only
+ OpenGL). This way the application will work correctly in all Qt build
+ configurations, including the ones that perform dynamic OpenGL implementation
+ loading which means applications are not directly linking to an GL
+ implementation and thus direct function calls are not feasible.
+
+ In paintGL() the current context is always accessible by caling
+ QOpenGLContext::currentContext(). From this context an already initialized,
+ ready-to-be-used QOpenGLFunctions instance is retrievable by calling
+ QOpenGLContext::functions(). An alternative to prefixing every GL call is to
+ inherit from QOpenGLFunctions and call
+ QOpenGLFunctions::initializeOpenGLFunctions() in initializeGL().
+
+ As for the OpenGL headers, note that in most cases there will be no need to
+ directly include any headers like GL.h. The OpenGL-related Qt headers will
+ include qopengl.h which will in turn include an appropriate header for the
+ system. This might be an OpenGL ES 3.x or 2.0 header, the highest version that
+ is available, or a system-provided gl.h. In addition, a copy of the extension
+ headers (called glext.h on some systems) is provided as part of Qt both for
+ OpenGL and OpenGL ES. These will get included automatically on platforms where
+ feasible. This means that constants and function pointer typedefs from ARB,
+ EXT, OES extensions are automatically available.
+
+ \section1 Code Examples
+
+ To get started, the simplest QOpenGLWidget subclass could like like the following:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 0
+
+ Alternatively, the prefixing of each and every OpenGL call can be avoided by deriving
+ from QOpenGLFunctions instead:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 1
+
+ To get a context compatible with a given OpenGL version or profile, or to
+ request depth and stencil buffers, call setFormat():
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 2
+
+ With OpenGL 3.0+ contexts, when portability is not important, the versioned
+ QOpenGLFunctions variants give easy access to all the modern OpenGL functions
+ available in a given version:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 3
+
+ As described above, it is simpler and more robust to set the requested format
+ globally so that it applies to all windows and contexts during the lifetime of
+ the application. Below is an example of this:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 6
+
+ \section1 Relation to QGLWidget
+
+ The legacy QtOpenGL module (classes prefixed with QGL) provides a widget
+ called QGLWidget. QOpenGLWidget is intended to be a modern replacement for
+ it. Therefore, especially in new applications, the general recommendation is
+ to use QOpenGLWidget.
+
+ While the API is very similar, there is an important difference between the
+ two: QOpenGLWidget always renders offscreen, using framebuffer
+ objects. QGLWidget on the other hand uses a native window and surface. The
+ latter causes issues when using it in complex user interfaces since, depending
+ on the platform, such native child widgets may have various limitations,
+ regarding stacking orders for example. QOpenGLWidget avoids this by not
+ creating a separate native window.
+
+ Due to being backed by a framebuffer object, the behavior of QOpenGLWidget is
+ very similar to QOpenGLWindow with the update behavior set to \c
+ PartialUpdateBlit or \c PartialUpdateBlend. This means that the contents are
+ preserved between paintGL() calls so that incremental rendering is
+ possible. With QGLWidget (and naturally QOpenGLWindow with the default update
+ behavior) this is usually not the case because swapping the buffers leaves the
+ back buffer with undefined contents.
+
+ \note Most applications do not need incremental rendering because they will
+ render everything in the view on every paint call. In this case it is
+ important to call glClear() as early as possible in paintGL(). This helps
+ mobile GPUs that use a tile-based architecture to recognize that the tile
+ buffer does not need to be reloaded with the framebuffer's previous
+ contents. Omitting the clear call can lead to significant performance drops on
+ such systems.
+
+ \note Avoid calling winId() on a QOpenGLWidget. This function triggers the creation of
+ a native window, resulting in reduced performance and possibly rendering glitches.
+
+ \section1 Differences to QGLWidget
+
+ Besides the main conceptual difference of being backed by a framebuffer object, there
+ are a number of smaller, internal differences between QOpenGLWidget and the older
+ QGLWidget:
+
+ \list
+
+ \li OpenGL state when invoking paintGL(). QOpenGLWidget sets up the viewport via
+ glViewport(). It does not perform any clearing.
+
+ \li Clearing when starting to paint via QPainter. Unlike regular widgets, QGLWidget
+ defaulted to a value of \c true for
+ \l{QWidget::autoFillBackground()}{autoFillBackground}. It then performed clearing to the
+ palette's background color every time QPainter::begin() was used. QOpenGLWidget does not
+ follow this: \l{QWidget::autoFillBackground()}{autoFillBackground} defaults to false,
+ like for any other widget. The only exception is when being used as a viewport for other
+ widgets like QGraphicsView. In such a case autoFillBackground will be automatically set
+ to true to ensure compatibility with QGLWidget-based viewports.
+
+ \endlist
+
+ \section1 Multisampling
+
+ To enable multisampling, set the number of requested samples on the
+ QSurfaceFormat that is passed to setFormat(). On systems that do not support
+ it the request may get ignored.
+
+ Multisampling support requires support for multisampled renderbuffers and
+ framebuffer blits. On OpenGL ES 2.0 implementations it is likely that these
+ will not be present. This means that multisampling will not be available. With
+ modern OpenGL versions and OpenGL ES 3.0 and up this is usually not a problem
+ anymore.
+
+ \section1 Threading
+
+ Performing offscreen rendering on worker threads, for example to generate
+ textures that are then used in the GUI/main thread in paintGL(), are supported
+ by exposing the widget's QOpenGLContext so that additional contexts sharing
+ with it can be created on each thread.
+
+ Drawing directly to the QOpenGLWidget's framebuffer outside the GUI/main
+ thread is possible by reimplementing paintEvent() to do nothing. The context's
+ thread affinity has to be changed via QObject::moveToThread(). After that,
+ makeCurrent() and doneCurrent() are usable on the worker thread. Be careful to
+ move the context back to the GUI/main thread afterwards.
+
+ Unlike QGLWidget, triggering a buffer swap just for the QOpenGLWidget is not
+ possible since there is no real, onscreen native surface for it. Instead, it
+ is up to the widget stack to manage composition and buffer swaps on the gui
+ thread. When a thread is done updating the framebuffer, call update() \b{on
+ the GUI/main thread} to schedule composition.
+
+ Extra care has to be taken to avoid using the framebuffer when the GUI/main
+ thread is performing compositing. The signals aboutToCompose() and
+ frameSwapped() will be emitted when the composition is starting and
+ ending. They are emitted on the GUI/main thread. This means that by using a
+ direct connection aboutToCompose() can block the GUI/main thread until the
+ worker thread has finished its rendering. After that, the worker thread must
+ perform no further rendering until the frameSwapped() signal is emitted. If
+ this is not acceptable, the worker thread has to implement a double buffering
+ mechanism. This involves drawing using an alternative render target, that is
+ fully controlled by the thread, e.g. an additional framebuffer object, and
+ blitting to the QOpenGLWidget's framebuffer at a suitable time.
+
+ \section1 Context Sharing
+
+ When multiple QOpenGLWidgets are added as children to the same top-level
+ widget, their contexts will share with each other. This does not apply for
+ QOpenGLWidget instances that belong to different windows.
+
+ This means that all QOpenGLWidgets in the same window can access each other's
+ sharable resources, like textures, and there is no need for an extra "global
+ share" context, as was the case with QGLWidget.
+
+ To set up sharing between QOpenGLWidget instances belonging to different
+ windows, set the Qt::AA_ShareOpenGLContexts application attribute before
+ instantiating QApplication. This will trigger sharing between all
+ QOpenGLWidget instances without any further steps.
+
+ Creating extra QOpenGLContext instances that share resources like textures
+ with the QOpenGLWidget's context is also possible. Simply pass the pointer
+ returned from context() to QOpenGLContext::setShareContext() before calling
+ QOpenGLContext::create(). The resulting context can also be used on a
+ different thread, allowing threaded generation of textures and asynchronous
+ texture uploads.
+
+ Note that QOpenGLWidget expects a standard conformant implementation of
+ resource sharing when it comes to the underlying graphics drivers. For
+ example, some drivers, in particular for mobile and embedded hardware, have
+ issues with setting up sharing between an existing context and others that are
+ created later. Some other drivers may behave in unexpected ways when trying to
+ utilize shared resources between different threads.
+
+ \section1 Resource Initialization and Cleanup
+
+ The QOpenGLWidget's associated OpenGL context is guaranteed to be current
+ whenever initializeGL() and paintGL() are invoked. Do not attempt to create
+ OpenGL resources before initializeGL() is called. For example, attempting to
+ compile shaders, initialize vertex buffer objects or upload texture data will
+ fail when done in a subclass's constructor. These operations must be deferred
+ to initializeGL(). Some of Qt's OpenGL helper classes, like QOpenGLBuffer or
+ QOpenGLVertexArrayObject, have a matching deferred behavior: they can be
+ instantiated without a context, but all initialization is deferred until a
+ create(), or similar, call. This means that they can be used as normal
+ (non-pointer) member variables in a QOpenGLWidget subclass, but the create()
+ or similar function can only be called from initializeGL(). Be aware however
+ that not all classes are designed like this. When in doubt, make the member
+ variable a pointer and create and destroy the instance dynamically in
+ initializeGL() and the destructor, respectively.
+
+ Releasing the resources also needs the context to be current. Therefore
+ destructors that perform such cleanup are expected to call makeCurrent()
+ before moving on to destroy any OpenGL resources or wrappers. Avoid deferred
+ deletion via \l{QObject::deleteLater()}{deleteLater()} or the parenting
+ mechanism of QObject. There is no guarantee the correct context will be
+ current at the time the instance in question is really destroyed.
+
+ A typical subclass will therefore often look like the following when it comes
+ to resource initialization and destruction:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 4
+
+ This is naturally not the only possible solution. One alternative is to use
+ the \l{QOpenGLContext::aboutToBeDestroyed()}{aboutToBeDestroyed()} signal of
+ QOpenGLContext. By connecting a slot, using direct connection, to this signal,
+ it is possible to perform cleanup whenever the underlying native context
+ handle, or the entire QOpenGLContext instance, is going to be released. The
+ following snippet is in principle equivalent to the previous one:
+
+ \snippet code/doc_gui_widgets_qopenglwidget.cpp 5
+
+ \note For widgets that change their associated top-level window multiple times
+ during their lifetime, a combined approach is essential. Whenever the widget
+ or a parent of it gets reparented so that the top-level window becomes
+ different, the widget's associated context is destroyed and a new one is
+ created. This is then followed by a call to initializeGL() where all OpenGL
+ resources must get reinitialized. Due to this the only option to perform
+ proper cleanup is to connect to the context's aboutToBeDestroyed()
+ signal. Note that the context in question may not be the current one when the
+ signal gets emitted. Therefore it is good practice to call makeCurrent() in
+ the connected slot. Additionally, the same cleanup steps must be performed
+ from the derived class' destructor, since the slot connected to the signal
+ will not get invoked when the widget is being destroyed.
+
+ \note When Qt::AA_ShareOpenGLContexts is set, the widget's context never
+ changes, not even when reparenting because the widget's associated texture is
+ guaranteed to be accessible also from the new top-level's context.
+
+ Proper cleanup is especially important due to context sharing. Even though
+ each QOpenGLWidget's associated context is destroyed together with the
+ QOpenGLWidget, the sharable resources in that context, like textures, will
+ stay valid until the top-level window, in which the QOpenGLWidget lived, is
+ destroyed. Additionally, settings like Qt::AA_ShareOpenGLContexts and some Qt
+ modules may trigger an even wider scope for sharing contexts, potentially
+ leading to keeping the resources in question alive for the entire lifetime of
+ the application. Therefore the safest and most robust is always to perform
+ explicit cleanup for all resources and resource wrappers used in the
+ QOpenGLWidget.
+
+ \section1 Limitations
+
+ Putting other widgets underneath and making the QOpenGLWidget transparent will
+ not lead to the expected results: The widgets underneath will not be
+ visible. This is because in practice the QOpenGLWidget is drawn before all
+ other regular, non-OpenGL widgets, and so see-through type of solutions are
+ not feasible. Other type of layouts, like having widgets on top of the
+ QOpenGLWidget, will function as expected.
+
+ When absolutely necessary, this limitation can be overcome by setting the
+ Qt::WA_AlwaysStackOnTop attribute on the QOpenGLWidget. Be aware however that
+ this breaks stacking order, for example it will not be possible to have other
+ widgets on top of the QOpenGLWidget, so it should only be used in situations
+ where a semi-transparent QOpenGLWidget with other widgets visible underneath
+ is required.
+
+ Note that this does not apply when there are no other widgets underneath and
+ the intention is to have a semi-transparent window. In that case the
+ traditional approach of setting Qt::WA_TranslucentBackground
+ on the top-level window is sufficient. Note that if the transparent areas are
+ only desired in the QOpenGLWidget, then Qt::WA_NoSystemBackground will need
+ to be turned back to \c false after enabling Qt::WA_TranslucentBackground.
+ Additionally, requesting an alpha channel for the QOpenGLWidget's context via
+ setFormat() may be necessary too, depending on the system.
+
+ QOpenGLWidget supports multiple update behaviors, just like QOpenGLWindow. In
+ preserved mode the rendered content from the previous paintGL() call is
+ available in the next one, allowing incremental rendering. In non-preserved
+ mode the content is lost and paintGL() implementations are expected to redraw
+ everything in the view.
+
+ Before Qt 5.5 the default behavior of QOpenGLWidget was to preserve the
+ rendered contents between paintGL() calls. Since Qt 5.5 the default behavior
+ is non-preserved because this provides better performance and the majority of
+ applications have no need for the previous content. This also resembles the
+ semantics of an OpenGL-based QWindow and matches the default behavior of
+ QOpenGLWindow in that the color and ancillary buffers are invalidated for
+ each frame. To restore the preserved behavior, call setUpdateBehavior() with
+ \c PartialUpdate.
+
+ \section1 Alternatives
+
+ Adding a QOpenGLWidget into a window turns on OpenGL-based
+ compositing for the entire window. In some special cases this may
+ not be ideal, and the old QGLWidget-style behavior with a separate,
+ native child window is desired. Desktop applications that understand
+ the limitations of this approach (for example when it comes to
+ overlaps, transparency, scroll views and MDI areas), can use
+ QOpenGLWindow with QWidget::createWindowContainer(). This is a
+ modern alternative to QGLWidget and is faster than QOpenGLWidget due
+ to the lack of the additional composition step. It is strongly
+ recommended to limit the usage of this approach to cases where there
+ is no other choice. Note that this option is not suitable for most
+ embedded and mobile platforms, and it is known to have issues on
+ certain desktop platforms (e.g. \macos) too. The stable,
+ cross-platform solution is always QOpenGLWidget.
+
+ \e{OpenGL is a trademark of Silicon Graphics, Inc. in the United States and other
+ countries.}
+
+ \sa QOpenGLFunctions, QOpenGLWindow, Qt::AA_ShareOpenGLContexts, UpdateBehavior
+*/
+
+/*!
+ \fn void QOpenGLWidget::aboutToCompose()
+
+ This signal is emitted when the widget's top-level window is about to begin
+ composing the textures of its QOpenGLWidget children and the other widgets.
+*/
+
+/*!
+ \fn void QOpenGLWidget::frameSwapped()
+
+ This signal is emitted after the widget's top-level window has finished
+ composition and returned from its potentially blocking
+ QOpenGLContext::swapBuffers() call.
+*/
+
+/*!
+ \fn void QOpenGLWidget::aboutToResize()
+
+ This signal is emitted when the widget's size is changed and therefore the
+ framebuffer object is going to be recreated.
+*/
+
+/*!
+ \fn void QOpenGLWidget::resized()
+
+ This signal is emitted right after the framebuffer object has been recreated
+ due to resizing the widget.
+*/
+
+/*!
+ \enum QOpenGLWidget::UpdateBehavior
+ \since 5.5
+
+ This enum describes the update semantics of QOpenGLWidget.
+
+ \value NoPartialUpdate QOpenGLWidget will discard the
+ contents of the color buffer and the ancillary buffers after the
+ QOpenGLWidget is rendered to screen. This is the same behavior that can be
+ expected by calling QOpenGLContext::swapBuffers with a default opengl
+ enabled QWindow as the argument. NoPartialUpdate can have some performance
+ benefits on certain hardware architectures common in the mobile and
+ embedded space when a framebuffer object is used as the rendering target.
+ The framebuffer object is invalidated between frames with
+ glDiscardFramebufferEXT if supported or a glClear. Please see the
+ documentation of EXT_discard_framebuffer for more information:
+ https://www.khronos.org/registry/gles/extensions/EXT/EXT_discard_framebuffer.txt
+
+ \value PartialUpdate The framebuffer objects color buffer and ancillary
+ buffers are not invalidated between frames.
+
+ \sa updateBehavior(), setUpdateBehavior()
+*/
+
+class QOpenGLWidgetPaintDevicePrivate : public QOpenGLPaintDevicePrivate
+{
+public:
+ QOpenGLWidgetPaintDevicePrivate(QOpenGLWidget *widget)
+ : QOpenGLPaintDevicePrivate(QSize()),
+ w(widget) { }
+
+ void beginPaint() override;
+ void endPaint() override;
+
+ QOpenGLWidget *w;
+};
+
+class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLWidgetPaintDevice(QOpenGLWidget *widget)
+ : QOpenGLPaintDevice(*new QOpenGLWidgetPaintDevicePrivate(widget)) { }
+ void ensureActiveTarget() override;
+};
+
+class QOpenGLWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLWidget)
+public:
+ QOpenGLWidgetPrivate()
+ : context(nullptr),
+ fbo(nullptr),
+ resolvedFbo(nullptr),
+ surface(nullptr),
+ initialized(false),
+ fakeHidden(false),
+ inBackingStorePaint(false),
+ hasBeenComposed(false),
+ flushPending(false),
+ paintDevice(nullptr),
+ updateBehavior(QOpenGLWidget::NoPartialUpdate),
+ requestedSamples(0),
+ inPaintGL(false),
+ textureFormat(0)
+ {
+ requestedFormat = QSurfaceFormat::defaultFormat();
+ }
+
+ void reset();
+ void recreateFbo();
+
+ GLuint textureId() const override;
+ QPlatformTextureList::Flags textureListFlags() override;
+
+ void initialize();
+ void invokeUserPaint();
+ void render();
+
+ void invalidateFbo();
+
+ QImage grabFramebuffer() override;
+ void beginBackingStorePainting() override { inBackingStorePaint = true; }
+ void endBackingStorePainting() override { inBackingStorePaint = false; }
+ void beginCompose() override;
+ void endCompose() override;
+ void initializeViewportFramebuffer() override;
+ void resizeViewportFramebuffer() override;
+ void resolveSamples() override;
+
+ QOpenGLContext *context;
+ QOpenGLFramebufferObject *fbo;
+ QOpenGLFramebufferObject *resolvedFbo;
+ QOffscreenSurface *surface;
+ bool initialized;
+ bool fakeHidden;
+ bool inBackingStorePaint;
+ bool hasBeenComposed;
+ bool flushPending;
+ QOpenGLPaintDevice *paintDevice;
+ QSurfaceFormat requestedFormat;
+ QOpenGLWidget::UpdateBehavior updateBehavior;
+ int requestedSamples;
+ bool inPaintGL;
+ GLenum textureFormat;
+};
+
+void QOpenGLWidgetPaintDevicePrivate::beginPaint()
+{
+ // NB! autoFillBackground is and must be false by default. Otherwise we would clear on
+ // every QPainter begin() which is not desirable. This is only for legacy use cases,
+ // like using QOpenGLWidget as the viewport of a graphics view, that expect clearing
+ // with the palette's background color.
+ if (w->autoFillBackground()) {
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ if (w->format().hasAlpha()) {
+ f->glClearColor(0, 0, 0, 0);
+ } else {
+ QColor c = w->palette().brush(w->backgroundRole()).color();
+ float alpha = c.alphaF();
+ f->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
+ }
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+}
+
+void QOpenGLWidgetPaintDevicePrivate::endPaint()
+{
+ QOpenGLWidgetPrivate *wd = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(w));
+ if (!wd->initialized)
+ return;
+
+ if (!wd->inPaintGL)
+ QOpenGLContextPrivate::get(wd->context)->defaultFboRedirect = 0;
+}
+
+void QOpenGLWidgetPaintDevice::ensureActiveTarget()
+{
+ QOpenGLWidgetPaintDevicePrivate *d = static_cast<QOpenGLWidgetPaintDevicePrivate *>(d_ptr.data());
+ QOpenGLWidgetPrivate *wd = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(d->w));
+ if (!wd->initialized)
+ return;
+
+ if (QOpenGLContext::currentContext() != wd->context)
+ d->w->makeCurrent();
+ else
+ wd->fbo->bind();
+
+ if (!wd->inPaintGL)
+ QOpenGLContextPrivate::get(wd->context)->defaultFboRedirect = wd->fbo->handle();
+
+ // When used as a viewport, drawing is done via opening a QPainter on the widget
+ // without going through paintEvent(). We will have to make sure a glFlush() is done
+ // before the texture is accessed also in this case.
+ wd->flushPending = true;
+}
+
+GLuint QOpenGLWidgetPrivate::textureId() const
+{
+ return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
+}
+
+#ifndef GL_SRGB
+#define GL_SRGB 0x8C40
+#endif
+#ifndef GL_SRGB8
+#define GL_SRGB8 0x8C41
+#endif
+#ifndef GL_SRGB_ALPHA
+#define GL_SRGB_ALPHA 0x8C42
+#endif
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
+QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags()
+{
+ QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
+ switch (textureFormat) {
+ case GL_SRGB:
+ case GL_SRGB8:
+ case GL_SRGB_ALPHA:
+ case GL_SRGB8_ALPHA8:
+ flags |= QPlatformTextureList::TextureIsSrgb;
+ break;
+ default:
+ break;
+ }
+ return flags;
+}
+
+void QOpenGLWidgetPrivate::reset()
+{
+ Q_Q(QOpenGLWidget);
+
+ // Destroy the OpenGL resources first. These need the context to be current.
+ if (initialized)
+ q->makeCurrent();
+
+ delete paintDevice;
+ paintDevice = nullptr;
+ delete fbo;
+ fbo = nullptr;
+ delete resolvedFbo;
+ resolvedFbo = nullptr;
+
+ if (initialized)
+ q->doneCurrent();
+
+ // Delete the context first, then the surface. Slots connected to
+ // the context's aboutToBeDestroyed() may still call makeCurrent()
+ // to perform some cleanup.
+ delete context;
+ context = nullptr;
+ delete surface;
+ surface = nullptr;
+ initialized = fakeHidden = inBackingStorePaint = false;
+}
+
+void QOpenGLWidgetPrivate::recreateFbo()
+{
+ Q_Q(QOpenGLWidget);
+
+ emit q->aboutToResize();
+
+ context->makeCurrent(surface);
+
+ delete fbo;
+ fbo = nullptr;
+ delete resolvedFbo;
+ resolvedFbo = nullptr;
+
+ int samples = requestedSamples;
+ QOpenGLExtensions *extfuncs = static_cast<QOpenGLExtensions *>(context->functions());
+ if (!extfuncs->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
+ samples = 0;
+
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setSamples(samples);
+ if (textureFormat)
+ format.setInternalTextureFormat(textureFormat);
+
+ const QSize deviceSize = q->size() * q->devicePixelRatioF();
+ fbo = new QOpenGLFramebufferObject(deviceSize, format);
+ if (samples > 0)
+ resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
+
+ textureFormat = fbo->format().internalTextureFormat();
+
+ fbo->bind();
+ context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ flushPending = true; // Make sure the FBO is initialized before use
+
+ paintDevice->setSize(deviceSize);
+ paintDevice->setDevicePixelRatio(q->devicePixelRatioF());
+
+ emit q->resized();
+}
+
+void QOpenGLWidgetPrivate::beginCompose()
+{
+ Q_Q(QOpenGLWidget);
+ if (flushPending) {
+ flushPending = false;
+ q->makeCurrent();
+ static_cast<QOpenGLExtensions *>(context->functions())->flushShared();
+ }
+ hasBeenComposed = true;
+ emit q->aboutToCompose();
+}
+
+void QOpenGLWidgetPrivate::endCompose()
+{
+ Q_Q(QOpenGLWidget);
+ emit q->frameSwapped();
+}
+
+void QOpenGLWidgetPrivate::initialize()
+{
+ Q_Q(QOpenGLWidget);
+ if (initialized)
+ return;
+
+ // If no global shared context get our toplevel's context with which we
+ // will share in order to make the texture usable by the underlying window's backingstore.
+ QWidget *tlw = q->window();
+ QOpenGLContext *shareContext = qt_gl_global_share_context();
+ if (!shareContext)
+ shareContext = get(tlw)->shareContext();
+ // If shareContext is null, showing content on-screen will not work.
+ // However, offscreen rendering and grabFramebuffer() will stay fully functional.
+
+ // Do not include the sample count. Requesting a multisampled context is not necessary
+ // since we render into an FBO, never to an actual surface. What's more, attempting to
+ // create a pbuffer with a multisampled config crashes certain implementations. Just
+ // avoid the entire hassle, the result is the same.
+ requestedSamples = requestedFormat.samples();
+ requestedFormat.setSamples(0);
+
+ QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
+ ctx->setFormat(requestedFormat);
+ if (shareContext) {
+ ctx->setShareContext(shareContext);
+ ctx->setScreen(shareContext->screen());
+ }
+ if (Q_UNLIKELY(!ctx->create())) {
+ qWarning("QOpenGLWidget: Failed to create context");
+ return;
+ }
+
+ // Propagate settings that make sense only for the tlw. Note that this only
+ // makes sense for properties that get picked up even after the native
+ // window is created.
+ if (tlw->windowHandle()) {
+ QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
+ if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
+ // Most platforms will pick up the changed swap interval on the next
+ // makeCurrent or swapBuffers.
+ tlwFormat.setSwapInterval(requestedFormat.swapInterval());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
+ if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
+ tlwFormat.setSwapBehavior(requestedFormat.swapBehavior());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
+ }
+
+ // The top-level window's surface is not good enough since it causes way too
+ // much trouble with regards to the QSurfaceFormat for example. So just like
+ // in QQuickWidget, use a dedicated QOffscreenSurface.
+ surface = new QOffscreenSurface;
+ surface->setFormat(ctx->format());
+ surface->setScreen(ctx->screen());
+ surface->create();
+
+ if (Q_UNLIKELY(!ctx->makeCurrent(surface))) {
+ qWarning("QOpenGLWidget: Failed to make context current");
+ return;
+ }
+
+ paintDevice = new QOpenGLWidgetPaintDevice(q);
+ paintDevice->setSize(q->size() * q->devicePixelRatioF());
+ paintDevice->setDevicePixelRatio(q->devicePixelRatioF());
+
+ context = ctx.take();
+ initialized = true;
+
+ q->initializeGL();
+}
+
+void QOpenGLWidgetPrivate::resolveSamples()
+{
+ Q_Q(QOpenGLWidget);
+ if (resolvedFbo) {
+ q->makeCurrent();
+ QRect rect(QPoint(0, 0), fbo->size());
+ QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
+ flushPending = true;
+ }
+}
+
+void QOpenGLWidgetPrivate::invokeUserPaint()
+{
+ Q_Q(QOpenGLWidget);
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ Q_ASSERT(ctx && fbo);
+
+ QOpenGLFunctions *f = ctx->functions();
+ QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = fbo->handle();
+
+ f->glViewport(0, 0, q->width() * q->devicePixelRatioF(), q->height() * q->devicePixelRatioF());
+ inPaintGL = true;
+ q->paintGL();
+ inPaintGL = false;
+ flushPending = true;
+
+ QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = 0;
+}
+
+void QOpenGLWidgetPrivate::render()
+{
+ Q_Q(QOpenGLWidget);
+
+ if (fakeHidden || !initialized)
+ return;
+
+ q->makeCurrent();
+
+ if (updateBehavior == QOpenGLWidget::NoPartialUpdate && hasBeenComposed) {
+ invalidateFbo();
+ hasBeenComposed = false;
+ }
+
+ invokeUserPaint();
+}
+
+void QOpenGLWidgetPrivate::invalidateFbo()
+{
+ QOpenGLExtensions *f = static_cast<QOpenGLExtensions *>(QOpenGLContext::currentContext()->functions());
+ if (f->hasOpenGLExtension(QOpenGLExtensions::DiscardFramebuffer)) {
+ const int gl_color_attachment0 = 0x8CE0; // GL_COLOR_ATTACHMENT0
+ const int gl_depth_attachment = 0x8D00; // GL_DEPTH_ATTACHMENT
+ const int gl_stencil_attachment = 0x8D20; // GL_STENCIL_ATTACHMENT
+#ifdef Q_OS_WASM
+ // webgl does not allow separate depth and stencil attachments
+ // QTBUG-69913
+ const int gl_depth_stencil_attachment = 0x821A; // GL_DEPTH_STENCIL_ATTACHMENT
+
+ const GLenum attachments[] = {
+ gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment, gl_depth_stencil_attachment
+ };
+#else
+ const GLenum attachments[] = {
+ gl_color_attachment0, gl_depth_attachment, gl_stencil_attachment
+ };
+#endif
+ f->glDiscardFramebufferEXT(GL_FRAMEBUFFER, sizeof attachments / sizeof *attachments, attachments);
+ } else {
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+}
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+QImage QOpenGLWidgetPrivate::grabFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+
+ initialize();
+ if (!initialized)
+ return QImage();
+
+ if (!fbo) // could be completely offscreen, without ever getting a resize event
+ recreateFbo();
+
+ if (!inPaintGL)
+ render();
+
+ if (resolvedFbo) {
+ resolveSamples();
+ resolvedFbo->bind();
+ } else {
+ q->makeCurrent();
+ }
+
+ const bool hasAlpha = q->format().hasAlpha();
+ QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatioF(), hasAlpha, hasAlpha);
+ res.setDevicePixelRatio(q->devicePixelRatioF());
+
+ // While we give no guarantees of what is going to be left bound, prefer the
+ // multisample fbo instead of the resolved one. Clients may continue to
+ // render straight after calling this function.
+ if (resolvedFbo)
+ q->makeCurrent();
+
+ return res;
+}
+
+void QOpenGLWidgetPrivate::initializeViewportFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+ // Legacy behavior for compatibility with QGLWidget when used as a graphics view
+ // viewport: enable clearing on each painter begin.
+ q->setAutoFillBackground(true);
+}
+
+void QOpenGLWidgetPrivate::resizeViewportFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+ if (!initialized)
+ return;
+
+ if (!fbo || q->size() * q->devicePixelRatioF() != fbo->size()) {
+ recreateFbo();
+ q->update();
+ }
+}
+
+/*!
+ Constructs a widget which is a child of \a parent, with widget flags set to \a f.
+ */
+QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*(new QOpenGLWidgetPrivate), parent, f)
+{
+ Q_D(QOpenGLWidget);
+ if (Q_UNLIKELY(!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)))
+ qWarning("QOpenGLWidget is not supported on this platform.");
+ else
+ d->setRenderToTexture();
+}
+
+/*!
+ Destroys the QOpenGLWidget instance, freeing its resources.
+
+ The QOpenGLWidget's context is made current in the destructor, allowing for
+ safe destruction of any child object that may need to release OpenGL
+ resources belonging to the context provided by this widget.
+
+ \warning if you have objects wrapping OpenGL resources (such as
+ QOpenGLBuffer, QOpenGLShaderProgram, etc.) as members of a OpenGLWidget
+ subclass, you may need to add a call to makeCurrent() in that subclass'
+ destructor as well. Due to the rules of C++ object destruction, those objects
+ will be destroyed \e{before} calling this function (but after that the
+ destructor of the subclass has run), therefore making the OpenGL context
+ current in this function happens too late for their safe disposal.
+
+ \sa makeCurrent
+*/
+QOpenGLWidget::~QOpenGLWidget()
+{
+ Q_D(QOpenGLWidget);
+ d->reset();
+}
+
+/*!
+ Sets this widget's update behavior to \a updateBehavior.
+ \since 5.5
+*/
+void QOpenGLWidget::setUpdateBehavior(UpdateBehavior updateBehavior)
+{
+ Q_D(QOpenGLWidget);
+ d->updateBehavior = updateBehavior;
+}
+
+/*!
+ \return the update behavior of the widget.
+ \since 5.5
+*/
+QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->updateBehavior;
+}
+
+/*!
+ Sets the requested surface \a format.
+
+ When the format is not explicitly set via this function, the format returned by
+ QSurfaceFormat::defaultFormat() will be used. This means that when having multiple
+ OpenGL widgets, individual calls to this function can be replaced by one single call to
+ QSurfaceFormat::setDefaultFormat() before creating the first widget.
+
+ \note Requesting an alpha buffer via this function will not lead to the
+ desired results when the intention is to make other widgets beneath visible.
+ Instead, use Qt::WA_AlwaysStackOnTop to enable semi-transparent QOpenGLWidget
+ instances with other widgets visible underneath. Keep in mind however that
+ this breaks the stacking order, so it will no longer be possible to have
+ other widgets on top of the QOpenGLWidget.
+
+ \sa format(), Qt::WA_AlwaysStackOnTop, QSurfaceFormat::setDefaultFormat()
+ */
+void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
+{
+ Q_D(QOpenGLWidget);
+ if (Q_UNLIKELY(d->initialized)) {
+ qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
+ return;
+ }
+
+ d->requestedFormat = format;
+}
+
+/*!
+ Returns the context and surface format used by this widget and its toplevel
+ window.
+
+ After the widget and its toplevel have both been created, resized and shown,
+ this function will return the actual format of the context. This may differ
+ from the requested format if the request could not be fulfilled by the
+ platform. It is also possible to get larger color buffer sizes than
+ requested.
+
+ When the widget's window and the related OpenGL resources are not yet
+ initialized, the return value is the format that has been set via
+ setFormat().
+
+ \sa setFormat(), context()
+ */
+QSurfaceFormat QOpenGLWidget::format() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->initialized ? d->context->format() : d->requestedFormat;
+}
+
+/*!
+ Sets a custom internal texture format of \a texFormat.
+
+ When working with sRGB framebuffers, it will be necessary to specify a
+ format like \c{GL_SRGB8_ALPHA8}. This can be achieved by calling this
+ function.
+
+ \note This function has no effect if called after the widget has already
+ been shown and thus it performed initialization.
+
+ \note This function will typically have to be used in combination with a
+ QSurfaceFormat::setDefaultFormat() call that sets the color space to
+ QSurfaceFormat::sRGBColorSpace.
+
+ \since 5.10
+ */
+void QOpenGLWidget::setTextureFormat(GLenum texFormat)
+{
+ Q_D(QOpenGLWidget);
+ if (Q_UNLIKELY(d->initialized)) {
+ qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect");
+ return;
+ }
+
+ d->textureFormat = texFormat;
+}
+
+/*!
+ \return the active internal texture format if the widget has already
+ initialized, the requested format if one was set but the widget has not yet
+ been made visible, or \nullptr if setTextureFormat() was not called and the
+ widget has not yet been made visible.
+
+ \since 5.10
+ */
+GLenum QOpenGLWidget::textureFormat() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->textureFormat;
+}
+
+/*!
+ \return \e true if the widget and OpenGL resources, like the context, have
+ been successfully initialized. Note that the return value is always false
+ until the widget is shown.
+*/
+bool QOpenGLWidget::isValid() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->initialized && d->context->isValid();
+}
+
+/*!
+ Prepares for rendering OpenGL content for this widget by making the
+ corresponding context current and binding the framebuffer object in that
+ context.
+
+ It is not necessary to call this function in most cases, because it
+ is called automatically before invoking paintGL().
+
+ \sa context(), paintGL(), doneCurrent()
+ */
+void QOpenGLWidget::makeCurrent()
+{
+ Q_D(QOpenGLWidget);
+ if (!d->initialized)
+ return;
+
+ d->context->makeCurrent(d->surface);
+
+ if (d->fbo) // there may not be one if we are in reset()
+ d->fbo->bind();
+}
+
+/*!
+ Releases the context.
+
+ It is not necessary to call this function in most cases, since the
+ widget will make sure the context is bound and released properly
+ when invoking paintGL().
+ */
+void QOpenGLWidget::doneCurrent()
+{
+ Q_D(QOpenGLWidget);
+ if (!d->initialized)
+ return;
+
+ d->context->doneCurrent();
+}
+
+/*!
+ \return The QOpenGLContext used by this widget or \c 0 if not yet initialized.
+
+ \note The context and the framebuffer object used by the widget changes when
+ reparenting the widget via setParent().
+
+ \sa QOpenGLContext::setShareContext(), defaultFramebufferObject()
+ */
+QOpenGLContext *QOpenGLWidget::context() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->context;
+}
+
+/*!
+ \return The framebuffer object handle or \c 0 if not yet initialized.
+
+ \note The framebuffer object belongs to the context returned by context()
+ and may not be accessible from other contexts.
+
+ \note The context and the framebuffer object used by the widget changes when
+ reparenting the widget via setParent(). In addition, the framebuffer object
+ changes on each resize.
+
+ \sa context()
+ */
+GLuint QOpenGLWidget::defaultFramebufferObject() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->fbo ? d->fbo->handle() : 0;
+}
+
+/*!
+ This virtual function is called once before the first call to
+ paintGL() or resizeGL(). Reimplement it in a subclass.
+
+ This function should set up any required OpenGL resources and state.
+
+ There is no need to call makeCurrent() because this has already been
+ done when this function is called. Note however that the framebuffer
+ is not yet available at this stage, so avoid issuing draw calls from
+ here. Defer such calls to paintGL() instead.
+
+ \sa paintGL(), resizeGL()
+*/
+void QOpenGLWidget::initializeGL()
+{
+}
+
+/*!
+ This virtual function is called whenever the widget has been
+ resized. Reimplement it in a subclass. The new size is passed in
+ \a w and \a h.
+
+ There is no need to call makeCurrent() because this has already been
+ done when this function is called. Additionally, the framebuffer is
+ also bound.
+
+ \sa initializeGL(), paintGL()
+*/
+void QOpenGLWidget::resizeGL(int w, int h)
+{
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+}
+
+/*!
+ This virtual function is called whenever the widget needs to be
+ painted. Reimplement it in a subclass.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+
+ Before invoking this function, the context and the framebuffer are
+ bound, and the viewport is set up by a call to glViewport(). No
+ other state is set and no clearing or drawing is performed by the
+ framework.
+
+ \sa initializeGL(), resizeGL()
+*/
+void QOpenGLWidget::paintGL()
+{
+}
+
+/*!
+ Handles resize events that are passed in the \a e event parameter.
+ Calls the virtual function resizeGL().
+
+ \note Avoid overriding this function in derived classes. If that is not
+ feasible, make sure that QOpenGLWidget's implementation is invoked
+ too. Otherwise the underlying framebuffer object and related resources will
+ not get resized properly and will lead to incorrect rendering.
+*/
+void QOpenGLWidget::resizeEvent(QResizeEvent *e)
+{
+ Q_D(QOpenGLWidget);
+
+ if (e->size().isEmpty()) {
+ d->fakeHidden = true;
+ return;
+ }
+ d->fakeHidden = false;
+
+ d->initialize();
+ if (!d->initialized)
+ return;
+
+ d->recreateFbo();
+ resizeGL(width(), height());
+ d->sendPaintEvent(QRect(QPoint(0, 0), size()));
+}
+
+/*!
+ Handles paint events.
+
+ Calling QWidget::update() will lead to sending a paint event \a e,
+ and thus invoking this function. (NB this is asynchronous and will
+ happen at some point after returning from update()). This function
+ will then, after some preparation, call the virtual paintGL() to
+ update the contents of the QOpenGLWidget's framebuffer. The widget's
+ top-level window will then composite the framebuffer's texture with
+ the rest of the window.
+*/
+void QOpenGLWidget::paintEvent(QPaintEvent *e)
+{
+ Q_UNUSED(e);
+ Q_D(QOpenGLWidget);
+ if (!d->initialized)
+ return;
+
+ if (updatesEnabled())
+ d->render();
+}
+
+/*!
+ Renders and returns a 32-bit RGB image of the framebuffer.
+
+ \note This is a potentially expensive operation because it relies on glReadPixels()
+ to read back the pixels. This may be slow and can stall the GPU pipeline.
+*/
+QImage QOpenGLWidget::grabFramebuffer()
+{
+ Q_D(QOpenGLWidget);
+ return d->grabFramebuffer();
+}
+
+/*!
+ \internal
+*/
+int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ Q_D(const QOpenGLWidget);
+ if (d->inBackingStorePaint)
+ return QWidget::metric(metric);
+
+ auto window = d->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel);
+ QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
+
+ const float dpmx = qt_defaultDpiX() * 100. / 2.54;
+ const float dpmy = qt_defaultDpiY() * 100. / 2.54;
+
+ switch (metric) {
+ case PdmWidth:
+ return width();
+ case PdmHeight:
+ return height();
+ case PdmDepth:
+ return 32;
+ case PdmWidthMM:
+ if (screen)
+ return width() * screen->physicalSize().width() / screen->geometry().width();
+ else
+ return width() * 1000 / dpmx;
+ case PdmHeightMM:
+ if (screen)
+ return height() * screen->physicalSize().height() / screen->geometry().height();
+ else
+ return height() * 1000 / dpmy;
+ case PdmNumColors:
+ return 0;
+ case PdmDpiX:
+ if (screen)
+ return qRound(screen->logicalDotsPerInchX());
+ else
+ return qRound(dpmx * 0.0254);
+ case PdmDpiY:
+ if (screen)
+ return qRound(screen->logicalDotsPerInchY());
+ else
+ return qRound(dpmy * 0.0254);
+ case PdmPhysicalDpiX:
+ if (screen)
+ return qRound(screen->physicalDotsPerInchX());
+ else
+ return qRound(dpmx * 0.0254);
+ case PdmPhysicalDpiY:
+ if (screen)
+ return qRound(screen->physicalDotsPerInchY());
+ else
+ return qRound(dpmy * 0.0254);
+ case PdmDevicePixelRatio:
+ if (window)
+ return int(window->devicePixelRatio());
+ else
+ return 1.0;
+ case PdmDevicePixelRatioScaled:
+ if (window)
+ return int(window->devicePixelRatio() * devicePixelRatioFScale());
+ else
+ return int(devicePixelRatioFScale());
+ default:
+ qWarning("QOpenGLWidget::metric(): unknown metric %d", metric);
+ return 0;
+ }
+}
+
+/*!
+ \internal
+*/
+QPaintDevice *QOpenGLWidget::redirected(QPoint *p) const
+{
+ Q_D(const QOpenGLWidget);
+ if (d->inBackingStorePaint)
+ return QWidget::redirected(p);
+
+ return d->paintDevice;
+}
+
+/*!
+ \internal
+*/
+QPaintEngine *QOpenGLWidget::paintEngine() const
+{
+ Q_D(const QOpenGLWidget);
+ // QWidget needs to "punch a hole" into the backingstore. This needs the
+ // normal paint engine and device, not the GL one. So in this mode, behave
+ // like a normal widget.
+ if (d->inBackingStorePaint)
+ return QWidget::paintEngine();
+
+ if (!d->initialized)
+ return nullptr;
+
+ return d->paintDevice->paintEngine();
+}
+
+/*!
+ \internal
+*/
+bool QOpenGLWidget::event(QEvent *e)
+{
+ Q_D(QOpenGLWidget);
+ switch (e->type()) {
+ case QEvent::WindowChangeInternal:
+ if (QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts))
+ break;
+ if (d->initialized)
+ d->reset();
+ if (isHidden())
+ break;
+ Q_FALLTHROUGH();
+ case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
+ if (d->initialized && window()->windowHandle()
+ && d->context->shareContext() != QWidgetPrivate::get(window())->shareContext())
+ {
+ // Special case: did grabFramebuffer() for a hidden widget that then became visible.
+ // Recreate all resources since the context now needs to share with the TLW's.
+ if (!QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts))
+ d->reset();
+ }
+ if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
+ d->initialize();
+ if (d->initialized)
+ d->recreateFbo();
+ }
+ break;
+ case QEvent::ScreenChangeInternal:
+ if (d->initialized && d->paintDevice->devicePixelRatioF() != devicePixelRatioF())
+ d->recreateFbo();
+ break;
+ default:
+ break;
+ }
+ return QWidget::event(e);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qopenglwidget.cpp"
diff --git a/src/opengl/qglpaintdevice_p.h b/src/opengl/qopenglwidget.h
index bfecdabd53..b266dc359d 100644
--- a/src/opengl/qglpaintdevice_p.h
+++ b/src/opengl/qopenglwidget.h
@@ -37,77 +37,79 @@
**
****************************************************************************/
-#ifndef QGLPAINTDEVICE_P_H
-#define QGLPAINTDEVICE_P_H
+#ifndef QOPENGLWIDGET_H
+#define QOPENGLWIDGET_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of the Qt OpenGL module. This header file may change from
-// version to version without notice, or even be removed.
-//
-// We mean it.
-//
+#include <QtOpenGL/qtopenglglobal.h>
+#ifdef QT_WIDGETS_LIB
-#include <qpaintdevice.h>
-#include <QtOpenGL/qgl.h>
-
+#include <QtWidgets/QWidget>
+#include <QtGui/QSurfaceFormat>
+#include <QtGui/qopengl.h>
QT_BEGIN_NAMESPACE
-class Q_OPENGL_EXPORT QGLPaintDevice : public QPaintDevice
+class QOpenGLWidgetPrivate;
+
+class Q_OPENGL_EXPORT QOpenGLWidget : public QWidget
{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QOpenGLWidget)
+
public:
- QGLPaintDevice();
- virtual ~QGLPaintDevice();
+ enum UpdateBehavior {
+ NoPartialUpdate,
+ PartialUpdate
+ };
- int devType() const override {return QInternal::OpenGL;}
+ explicit QOpenGLWidget(QWidget* parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
+ ~QOpenGLWidget();
- virtual void beginPaint();
- virtual void ensureActiveTarget();
- virtual void endPaint();
+ void setUpdateBehavior(UpdateBehavior updateBehavior);
+ UpdateBehavior updateBehavior() const;
- virtual QGLContext* context() const = 0;
- virtual QGLFormat format() const;
- virtual QSize size() const = 0;
- virtual bool alphaRequested() const;
- virtual bool isFlipped() const;
+ void setFormat(const QSurfaceFormat &format);
+ QSurfaceFormat format() const;
- // returns the QGLPaintDevice for the given QPaintDevice
- static QGLPaintDevice* getDevice(QPaintDevice*);
+ GLenum textureFormat() const;
+ void setTextureFormat(GLenum texFormat);
-protected:
- int metric(QPaintDevice::PaintDeviceMetric metric) const override;
- GLuint m_previousFBO;
- GLuint m_thisFBO;
-};
+ bool isValid() const;
+ void makeCurrent();
+ void doneCurrent();
-// Wraps a QGLWidget
-class QGLWidget;
-class Q_OPENGL_EXPORT QGLWidgetGLPaintDevice : public QGLPaintDevice
-{
-public:
- QGLWidgetGLPaintDevice();
+ QOpenGLContext *context() const;
+ GLuint defaultFramebufferObject() const;
+
+ QImage grabFramebuffer();
+
+Q_SIGNALS:
+ void aboutToCompose();
+ void frameSwapped();
+ void aboutToResize();
+ void resized();
- virtual QPaintEngine* paintEngine() const override;
+protected:
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
- // QGLWidgets need to do swapBufers in endPaint:
- virtual void beginPaint() override;
- virtual void endPaint() override;
- virtual QSize size() const override;
- virtual QGLContext* context() const override;
+ void paintEvent(QPaintEvent *e) override;
+ void resizeEvent(QResizeEvent *e) override;
+ bool event(QEvent *e) override;
- void setWidget(QGLWidget*);
+ int metric(QPaintDevice::PaintDeviceMetric metric) const override;
+ QPaintDevice *redirected(QPoint *p) const override;
+ QPaintEngine *paintEngine() const override;
private:
- friend class QGLWidget;
- QGLWidget *glWidget;
+ Q_DISABLE_COPY(QOpenGLWidget)
};
QT_END_NAMESPACE
-#endif // QGLPAINTDEVICE_P_H
+#endif // QT_WIDGETS_LIB
+
+#endif // QOPENGLWIDGET_H
diff --git a/src/opengl/qopenglwindow.cpp b/src/opengl/qopenglwindow.cpp
new file mode 100644
index 0000000000..5da20dc559
--- /dev/null
+++ b/src/opengl/qopenglwindow.cpp
@@ -0,0 +1,698 @@
+/****************************************************************************
+**
+** 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 "qopenglwindow.h"
+#include <QtGui/QOpenGLFramebufferObject>
+#include <QtGui/QOpenGLFunctions>
+#include <QtGui/private/qpaintdevicewindow_p.h>
+#include <QtGui/private/qopenglextensions_p.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtGui/QMatrix4x4>
+#include <QtGui/QOffscreenSurface>
+#include <QtOpenGL/QOpenGLTextureBlitter>
+#include <QtOpenGL/QOpenGLPaintDevice>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLWindow
+ \inmodule QtOpenGL
+ \since 5.4
+ \brief The QOpenGLWindow class is a convenience subclass of QWindow to perform OpenGL painting.
+
+ QOpenGLWindow is an enhanced QWindow that allows easily creating windows that
+ perform OpenGL rendering using an API that is compatible with QOpenGLWidget
+ and is similar to the legacy QGLWidget. Unlike QOpenGLWidget, QOpenGLWindow
+ has no dependency on the widgets module and offers better performance.
+
+ A typical application will subclass QOpenGLWindow and reimplement the following
+ virtual functions:
+
+ \list
+
+ \li initializeGL() to perform OpenGL resource initialization
+
+ \li resizeGL() to set up the transformation matrices and other window size dependent resources
+
+ \li paintGL() to issue OpenGL commands or draw using QPainter
+
+ \endlist
+
+ To schedule a repaint, call the update() function. Note that this will not
+ immediately result in a call to paintGL(). Calling update() multiple times in
+ a row will not change the behavior in any way.
+
+ This is a slot so it can be connected to a \l QTimer::timeout() signal to
+ perform animation. Note however that in the modern OpenGL world it is a much
+ better choice to rely on synchronization to the vertical refresh rate of the
+ display. See \l{QSurfaceFormat::setSwapInterval()}{setSwapInterval()} on a
+ description of the swap interval. With a swap interval of \c 1, which is the
+ case on most systems by default, the
+ \l{QOpenGLContext::swapBuffers()}{swapBuffers()} call, that is executed
+ internally by QOpenGLWindow after each repaint, will block and wait for
+ vsync. This means that whenever the swap is done, an update can be scheduled
+ again by calling update(), without relying on timers.
+
+ To request a specific configuration for the context, use setFormat()
+ like for any other QWindow. This allows, among others, requesting a
+ given OpenGL version and profile, or enabling depth and stencil
+ buffers.
+
+ Unlike QWindow, QOpenGLWindow allows opening a painter on itself and perform
+ QPainter-based drawing.
+
+ QOpenGLWindow supports multiple update behaviors. The default,
+ \c NoPartialUpdate is equivalent to a regular, OpenGL-based QWindow or the
+ legacy QGLWidget. In contrast, \c PartialUpdateBlit and \c PartialUpdateBlend are
+ more in line with QOpenGLWidget's way of working, where there is always an
+ extra, dedicated framebuffer object present. These modes allow, by
+ sacrificing some performance, redrawing only a smaller area on each paint and
+ having the rest of the content preserved from of the previous frame. This is
+ useful for applications than render incrementally using QPainter, because
+ this way they do not have to redraw the entire window content on each
+ paintGL() call.
+
+ Similarly to QOpenGLWidget, QOpenGLWindow supports the Qt::AA_ShareOpenGLContexts
+ attribute. When enabled, the OpenGL contexts of all QOpenGLWindow instances will share
+ with each other. This allows accessing each other's shareable OpenGL resources.
+
+ For more information on graphics in Qt, see \l {Graphics}.
+ */
+
+/*!
+ \enum QOpenGLWindow::UpdateBehavior
+
+ This enum describes the update strategy of the QOpenGLWindow.
+
+ \value NoPartialUpdate Indicates that the entire window surface will
+ redrawn on each update and so no additional framebuffers are needed.
+ This is the setting used in most cases and is equivalent to how drawing
+ directly via QWindow would function.
+
+ \value PartialUpdateBlit Indicates that the drawing performed in paintGL()
+ does not cover the entire window. In this case an extra framebuffer object
+ is created under the hood, and rendering performed in paintGL() will target
+ this framebuffer. This framebuffer is then blitted onto the window surface's
+ default framebuffer after each paint. This allows having QPainter-based drawing
+ code in paintGL() which only repaints a smaller area at a time, because, unlike
+ NoPartialUpdate, the previous content is preserved.
+
+ \value PartialUpdateBlend Similar to PartialUpdateBlit, but instead of using
+ framebuffer blits, the contents of the extra framebuffer is rendered by
+ drawing a textured quad with blending enabled. This, unlike PartialUpdateBlit,
+ allows alpha blended content and works even when the glBlitFramebuffer is
+ not available. Performance-wise this setting is likely to be somewhat slower
+ than PartialUpdateBlit.
+ */
+
+/*!
+ \fn void QOpenGLWindow::frameSwapped()
+
+ This signal is emitted after the potentially blocking
+ \l{QOpenGLContext::swapBuffers()}{buffer swap} has been done. Applications
+ that wish to continuously repaint synchronized to the vertical refresh,
+ should issue an update() upon this signal. This allows for a much smoother
+ experience compared to the traditional usage of timers.
+*/
+
+// GLES2 builds won't have these constants with the suffixless names
+#ifndef GL_READ_FRAMEBUFFER
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#endif
+#ifndef GL_DRAW_FRAMEBUFFER
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+
+class QOpenGLWindowPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLWindowPaintDevice(QOpenGLWindow *window) : m_window(window) { }
+ void ensureActiveTarget() override;
+
+ QOpenGLWindow *m_window;
+};
+
+class QOpenGLWindowPrivate : public QPaintDeviceWindowPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLWindow)
+public:
+ QOpenGLWindowPrivate(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior)
+ : updateBehavior(updateBehavior)
+ , hasFboBlit(false)
+ , shareContext(shareContext)
+ {
+ if (!shareContext)
+ this->shareContext = qt_gl_global_share_context();
+ }
+
+ ~QOpenGLWindowPrivate();
+
+ static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); }
+
+ void bindFBO();
+ void initialize();
+
+ void beginPaint(const QRegion &region) override;
+ void endPaint() override;
+ void flush(const QRegion &region) override;
+
+ QOpenGLWindow::UpdateBehavior updateBehavior;
+ bool hasFboBlit;
+ QScopedPointer<QOpenGLContext> context;
+ QOpenGLContext *shareContext;
+ QScopedPointer<QOpenGLFramebufferObject> fbo;
+ QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;
+ QOpenGLTextureBlitter blitter;
+ QColor backgroundColor;
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+};
+
+QOpenGLWindowPrivate::~QOpenGLWindowPrivate()
+{
+ Q_Q(QOpenGLWindow);
+ if (q->isValid()) {
+ q->makeCurrent(); // this works even when the platformwindow is destroyed
+ paintDevice.reset(nullptr);
+ fbo.reset(nullptr);
+ blitter.destroy();
+ q->doneCurrent();
+ }
+}
+
+void QOpenGLWindowPrivate::initialize()
+{
+ Q_Q(QOpenGLWindow);
+
+ if (context)
+ return;
+
+ if (!q->handle())
+ qWarning("Attempted to initialize QOpenGLWindow without a platform window");
+
+ context.reset(new QOpenGLContext);
+ context->setShareContext(shareContext);
+ context->setFormat(q->requestedFormat());
+ if (!context->create())
+ qWarning("QOpenGLWindow::beginPaint: Failed to create context");
+ if (!context->makeCurrent(q))
+ qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
+
+ paintDevice.reset(new QOpenGLWindowPaintDevice(q));
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
+ hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
+
+ q->initializeGL();
+}
+
+void QOpenGLWindowPrivate::beginPaint(const QRegion &region)
+{
+ Q_UNUSED(region);
+ Q_Q(QOpenGLWindow);
+
+ initialize();
+ context->makeCurrent(q);
+
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
+ const QSize deviceSize(deviceWidth, deviceHeight);
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+ if (!fbo || fbo->size() != deviceSize) {
+ QOpenGLFramebufferObjectFormat fboFormat;
+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ const int samples = q->requestedFormat().samples();
+ if (samples > 0) {
+ if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
+ fboFormat.setSamples(samples);
+ else
+ qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
+ }
+ fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
+ markWindowAsDirty();
+ }
+ } else {
+ markWindowAsDirty();
+ }
+
+ paintDevice->setSize(QSize(deviceWidth, deviceHeight));
+ paintDevice->setDevicePixelRatio(q->devicePixelRatio());
+ context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
+
+ context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
+
+ q->paintUnderGL();
+
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->bind();
+}
+
+void QOpenGLWindowPrivate::endPaint()
+{
+ Q_Q(QOpenGLWindow);
+
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->release();
+
+ context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
+
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
+ QOpenGLExtensions extensions(context.data());
+ extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
+ extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
+ extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
+ 0, 0, deviceWidth, deviceHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
+ context->functions()->glEnable(GL_BLEND);
+ context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ if (!blitter.isCreated())
+ blitter.create();
+
+ QRect windowRect(QPoint(0, 0), fbo->size());
+ QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);
+ blitter.bind();
+ blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);
+ blitter.release();
+
+ if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
+ context->functions()->glDisable(GL_BLEND);
+ }
+
+ q->paintOverGL();
+}
+
+void QOpenGLWindowPrivate::bindFBO()
+{
+ if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
+ fbo->bind();
+ else
+ QOpenGLFramebufferObject::bindDefault();
+}
+
+void QOpenGLWindowPrivate::flush(const QRegion &region)
+{
+ Q_UNUSED(region);
+ Q_Q(QOpenGLWindow);
+ context->swapBuffers(q);
+ emit q->frameSwapped();
+}
+
+void QOpenGLWindowPaintDevice::ensureActiveTarget()
+{
+ QOpenGLWindowPrivate::get(m_window)->bindFBO();
+}
+
+/*!
+ Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior.
+
+ \sa QOpenGLWindow::UpdateBehavior
+ */
+QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior, QWindow *parent)
+ : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(nullptr, updateBehavior)), parent)
+{
+ setSurfaceType(QSurface::OpenGLSurface);
+}
+
+/*!
+ Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior. The QOpenGLWindow's context will share with \a shareContext.
+
+ \sa QOpenGLWindow::UpdateBehavior shareContext
+*/
+QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, UpdateBehavior updateBehavior, QWindow *parent)
+ : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(shareContext, updateBehavior)), parent)
+{
+ setSurfaceType(QSurface::OpenGLSurface);
+}
+
+/*!
+ Destroys the QOpenGLWindow instance, freeing its resources.
+
+ The OpenGLWindow's context is made current in the destructor, allowing for
+ safe destruction of any child object that may need to release OpenGL
+ resources belonging to the context provided by this window.
+
+ \warning if you have objects wrapping OpenGL resources (such as
+ QOpenGLBuffer, QOpenGLShaderProgram, etc.) as members of a QOpenGLWindow
+ subclass, you may need to add a call to makeCurrent() in that subclass'
+ destructor as well. Due to the rules of C++ object destruction, those objects
+ will be destroyed \e{before} calling this function (but after that the
+ destructor of the subclass has run), therefore making the OpenGL context
+ current in this function happens too late for their safe disposal.
+
+ \sa makeCurrent
+
+ \since 5.5
+*/
+QOpenGLWindow::~QOpenGLWindow()
+{
+ makeCurrent();
+}
+
+/*!
+ \return the update behavior for this QOpenGLWindow.
+*/
+QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const
+{
+ Q_D(const QOpenGLWindow);
+ return d->updateBehavior;
+}
+
+/*!
+ \return \c true if the window's OpenGL resources, like the context, have
+ been successfully initialized. Note that the return value is always \c false
+ until the window becomes exposed (shown).
+*/
+bool QOpenGLWindow::isValid() const
+{
+ Q_D(const QOpenGLWindow);
+ return d->context && d->context->isValid();
+}
+
+/*!
+ Prepares for rendering OpenGL content for this window by making the
+ corresponding context current and binding the framebuffer object, if there is
+ one, in that context context.
+
+ It is not necessary to call this function in most cases, because it is called
+ automatically before invoking paintGL(). It is provided nonetheless to support
+ advanced, multi-threaded scenarios where a thread different than the GUI or main
+ thread may want to update the surface or framebuffer contents. See QOpenGLContext
+ for more information on threading related issues.
+
+ This function is suitable for calling also when the underlying platform window
+ is already destroyed. This means that it is safe to call this function from
+ a QOpenGLWindow subclass' destructor. If there is no native window anymore,
+ an offscreen surface is used instead. This ensures that OpenGL resource
+ cleanup operations in the destructor will always work, as long as
+ this function is called first.
+
+ \sa QOpenGLContext, context(), paintGL(), doneCurrent()
+ */
+void QOpenGLWindow::makeCurrent()
+{
+ Q_D(QOpenGLWindow);
+
+ if (!isValid())
+ return;
+
+ // The platform window may be destroyed at this stage and therefore
+ // makeCurrent() may not safely be called with 'this'.
+ if (handle()) {
+ d->context->makeCurrent(this);
+ } else {
+ if (!d->offscreenSurface) {
+ d->offscreenSurface.reset(new QOffscreenSurface(screen()));
+ d->offscreenSurface->setFormat(d->context->format());
+ d->offscreenSurface->create();
+ }
+ d->context->makeCurrent(d->offscreenSurface.data());
+ }
+
+ d->bindFBO();
+}
+
+/*!
+ Releases the context.
+
+ It is not necessary to call this function in most cases, since the widget
+ will make sure the context is bound and released properly when invoking
+ paintGL().
+
+ \sa makeCurrent()
+ */
+void QOpenGLWindow::doneCurrent()
+{
+ Q_D(QOpenGLWindow);
+
+ if (!isValid())
+ return;
+
+ d->context->doneCurrent();
+}
+
+/*!
+ \return The QOpenGLContext used by this window or \c 0 if not yet initialized.
+ */
+QOpenGLContext *QOpenGLWindow::context() const
+{
+ Q_D(const QOpenGLWindow);
+ return d->context.data();
+}
+
+/*!
+ \return The QOpenGLContext requested to be shared with this window's QOpenGLContext.
+*/
+QOpenGLContext *QOpenGLWindow::shareContext() const
+{
+ Q_D(const QOpenGLWindow);
+ return d->shareContext;
+}
+
+/*!
+ The framebuffer object handle used by this window.
+
+ When the update behavior is set to \c NoPartialUpdate, there is no separate
+ framebuffer object. In this case the returned value is the ID of the
+ default framebuffer.
+
+ Otherwise the value of the ID of the framebuffer object or \c 0 if not
+ yet initialized.
+ */
+GLuint QOpenGLWindow::defaultFramebufferObject() const
+{
+ Q_D(const QOpenGLWindow);
+ if (d->updateBehavior > NoPartialUpdate && d->fbo)
+ return d->fbo->handle();
+ else if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
+ return ctx->defaultFramebufferObject();
+ else
+ return 0;
+}
+
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
+/*!
+ Returns a copy of the framebuffer.
+
+ \note This is a potentially expensive operation because it relies on
+ glReadPixels() to read back the pixels. This may be slow and can stall the
+ GPU pipeline.
+
+ \note When used together with update behavior \c NoPartialUpdate, the returned
+ image may not contain the desired content when called after the front and back
+ buffers have been swapped (unless preserved swap is enabled in the underlying
+ windowing system interface). In this mode the function reads from the back
+ buffer and the contents of that may not match the content on the screen (the
+ front buffer). In this case the only place where this function can safely be
+ used is paintGL() or paintOverGL().
+ */
+QImage QOpenGLWindow::grabFramebuffer()
+{
+ if (!isValid())
+ return QImage();
+
+ makeCurrent();
+
+ const bool hasAlpha = format().hasAlpha();
+ QImage img = qt_gl_read_framebuffer(size() * devicePixelRatio(), hasAlpha, hasAlpha);
+ img.setDevicePixelRatio(devicePixelRatio());
+ return img;
+}
+
+/*!
+ This virtual function is called once before the first call to paintGL() or
+ resizeGL(). Reimplement it in a subclass.
+
+ This function should set up any required OpenGL resources and state.
+
+ There is no need to call makeCurrent() because this has already been done
+ when this function is called. Note however that the framebuffer, in case
+ partial update mode is used, is not yet available at this stage, so avoid
+ issuing draw calls from here. Defer such calls to paintGL() instead.
+
+ \sa paintGL(), resizeGL()
+ */
+void QOpenGLWindow::initializeGL()
+{
+}
+
+/*!
+ This virtual function is called whenever the widget has been resized.
+ Reimplement it in a subclass. The new size is passed in \a w and \a h.
+
+ \note This is merely a convenience function in order to provide an API that is
+ compatible with QOpenGLWidget. Unlike with QOpenGLWidget, derived classes are
+ free to choose to override resizeEvent() instead of this function.
+
+ \note Avoid issuing OpenGL commands from this function as there may not be a
+ context current when it is invoked. If it cannot be avoided, call makeCurrent().
+
+ \note Scheduling updates from here is not necessary. The windowing systems
+ will send expose events that trigger an update automatically.
+
+ \sa initializeGL(), paintGL()
+ */
+void QOpenGLWindow::resizeGL(int w, int h)
+{
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+}
+
+/*!
+ This virtual function is called whenever the window contents needs to be
+ painted. Reimplement it in a subclass.
+
+ There is no need to call makeCurrent() because this has already
+ been done when this function is called.
+
+ Before invoking this function, the context and the framebuffer, if there is
+ one, are bound, and the viewport is set up by a call to glViewport(). No
+ other state is set and no clearing or drawing is performed by the framework.
+
+ \note When using a partial update behavior, like \c PartialUpdateBlend, the
+ output of the previous paintGL() call is preserved and, after the additional
+ drawing perfomed in the current invocation of the function, the content is
+ blitted or blended over the content drawn directly to the window in
+ paintUnderGL().
+
+ \sa initializeGL(), resizeGL(), paintUnderGL(), paintOverGL(), UpdateBehavior
+ */
+void QOpenGLWindow::paintGL()
+{
+}
+
+/*!
+ The virtual function is called before each invocation of paintGL().
+
+ When the update mode is set to \c NoPartialUpdate, there is no difference
+ between this function and paintGL(), performing rendering in either of them
+ leads to the same result.
+
+ The difference becomes significant when using \c PartialUpdateBlend, where an
+ extra framebuffer object is used. There, paintGL() targets this additional
+ framebuffer object, which preserves its contents, while paintUnderGL() and
+ paintOverGL() target the default framebuffer, i.e. directly the window
+ surface, the contents of which is lost after each displayed frame.
+
+ \note Avoid relying on this function when the update behavior is
+ \c PartialUpdateBlit. This mode involves blitting the extra framebuffer used by
+ paintGL() onto the default framebuffer after each invocation of paintGL(),
+ thus overwriting all drawing generated in this function.
+
+ \sa paintGL(), paintOverGL(), UpdateBehavior
+ */
+void QOpenGLWindow::paintUnderGL()
+{
+}
+
+/*!
+ This virtual function is called after each invocation of paintGL().
+
+ When the update mode is set to NoPartialUpdate, there is no difference
+ between this function and paintGL(), performing rendering in either of them
+ leads to the same result.
+
+ Like paintUnderGL(), rendering in this function targets the default
+ framebuffer of the window, regardless of the update behavior. It gets called
+ after paintGL() has returned and the blit (PartialUpdateBlit) or quad drawing
+ (PartialUpdateBlend) has been done.
+
+ \sa paintGL(), paintUnderGL(), UpdateBehavior
+ */
+void QOpenGLWindow::paintOverGL()
+{
+}
+
+/*!
+ Paint \a event handler. Calls paintGL().
+
+ \sa paintGL()
+ */
+void QOpenGLWindow::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+ paintGL();
+}
+
+/*!
+ Resize \a event handler. Calls resizeGL().
+
+ \sa resizeGL()
+ */
+void QOpenGLWindow::resizeEvent(QResizeEvent *event)
+{
+ Q_UNUSED(event);
+ Q_D(QOpenGLWindow);
+ d->initialize();
+ resizeGL(width(), height());
+}
+
+/*!
+ \internal
+ */
+int QOpenGLWindow::metric(PaintDeviceMetric metric) const
+{
+ Q_D(const QOpenGLWindow);
+
+ switch (metric) {
+ case PdmDepth:
+ if (d->paintDevice)
+ return d->paintDevice->depth();
+ break;
+ default:
+ break;
+ }
+ return QPaintDeviceWindow::metric(metric);
+}
+
+/*!
+ \internal
+ */
+QPaintDevice *QOpenGLWindow::redirected(QPoint *) const
+{
+ Q_D(const QOpenGLWindow);
+ if (QOpenGLContext::currentContext() == d->context.data())
+ return d->paintDevice.data();
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qopenglwindow.h b/src/opengl/qopenglwindow.h
new file mode 100644
index 0000000000..926e4fabfd
--- /dev/null
+++ b/src/opengl/qopenglwindow.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** 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 QOPENGLWINDOW_H
+#define QOPENGLWINDOW_H
+
+#include <QtOpenGL/qtopenglglobal.h>
+
+#ifndef QT_NO_OPENGL
+
+#include <QtGui/QPaintDeviceWindow>
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QImage>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLWindowPrivate;
+
+class Q_OPENGL_EXPORT QOpenGLWindow : public QPaintDeviceWindow
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QOpenGLWindow)
+
+public:
+ enum UpdateBehavior {
+ NoPartialUpdate,
+ PartialUpdateBlit,
+ PartialUpdateBlend
+ };
+
+ explicit QOpenGLWindow(UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr);
+ explicit QOpenGLWindow(QOpenGLContext *shareContext, UpdateBehavior updateBehavior = NoPartialUpdate, QWindow *parent = nullptr);
+ ~QOpenGLWindow();
+
+ UpdateBehavior updateBehavior() const;
+ bool isValid() const;
+
+ void makeCurrent();
+ void doneCurrent();
+
+ QOpenGLContext *context() const;
+ QOpenGLContext *shareContext() const;
+
+ GLuint defaultFramebufferObject() const;
+
+ QImage grabFramebuffer();
+
+Q_SIGNALS:
+ void frameSwapped();
+
+protected:
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+ virtual void paintUnderGL();
+ virtual void paintOverGL();
+
+ void paintEvent(QPaintEvent *event) override;
+ void resizeEvent(QResizeEvent *event) override;
+ int metric(PaintDeviceMetric metric) const override;
+ QPaintDevice *redirected(QPoint *) const override;
+
+private:
+ Q_DISABLE_COPY(QOpenGLWindow)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_OPENGL
+
+#endif