summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gui/egl/qegl_p.h2
-rw-r--r--src/gui/egl/qegl_qpa.cpp2
-rw-r--r--src/gui/egl/qeglcontext_p.h2
-rw-r--r--src/gui/egl/qeglproperties_p.h2
-rw-r--r--src/gui/gui.pro1
-rw-r--r--src/gui/image/qpixmap.h2
-rw-r--r--src/gui/image/qplatformpixmap.cpp2
-rw-r--r--src/gui/image/qplatformpixmap_qpa.h2
-rw-r--r--src/gui/kernel/kernel.pri10
-rw-r--r--src/gui/kernel/qguiglcontext_qpa_p.h181
-rw-r--r--src/gui/kernel/qopenglcontext.cpp (renamed from src/gui/kernel/qguiglcontext_qpa.cpp)227
-rw-r--r--src/gui/kernel/qopenglcontext.h (renamed from src/gui/kernel/qguiglcontext_qpa.h)73
-rw-r--r--src/gui/kernel/qopenglcontext_p.h230
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.cpp4
-rw-r--r--src/gui/kernel/qplatformintegration_qpa.h4
-rw-r--r--src/gui/kernel/qplatformnativeinterface_qpa.cpp2
-rw-r--r--src/gui/kernel/qplatformnativeinterface_qpa.h4
-rw-r--r--src/gui/kernel/qplatformopenglcontext_qpa.cpp (renamed from src/gui/kernel/qplatformglcontext_qpa.cpp)48
-rw-r--r--src/gui/kernel/qplatformopenglcontext_qpa.h (renamed from src/gui/kernel/qplatformglcontext_qpa.h)22
-rw-r--r--src/gui/kernel/qplatformscreen_qpa.h2
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.cpp4
-rw-r--r--src/gui/kernel/qplatformwindow_qpa.h2
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp54
-rw-r--r--src/gui/kernel/qsurfaceformat.h12
-rw-r--r--src/gui/kernel/qwindow.cpp4
-rw-r--r--src/gui/opengl/opengl.pri44
-rw-r--r--src/gui/opengl/qopengl.cpp109
-rw-r--r--src/gui/opengl/qopengl.h73
-rw-r--r--src/gui/opengl/qopengl2pexvertexarray.cpp175
-rw-r--r--src/gui/opengl/qopengl2pexvertexarray_p.h169
-rw-r--r--src/gui/opengl/qopengl_p.h200
-rw-r--r--src/gui/opengl/qopenglbuffer.cpp582
-rw-r--r--src/gui/opengl/qopenglbuffer.h132
-rw-r--r--src/gui/opengl/qopenglcolormap.cpp297
-rw-r--r--src/gui/opengl/qopenglcolormap.h105
-rw-r--r--src/gui/opengl/qopenglcustomshaderstage.cpp138
-rw-r--r--src/gui/opengl/qopenglcustomshaderstage_p.h93
-rw-r--r--src/gui/opengl/qopenglengineshadermanager.cpp881
-rw-r--r--src/gui/opengl/qopenglengineshadermanager_p.h514
-rw-r--r--src/gui/opengl/qopenglengineshadersource_p.h529
-rw-r--r--src/gui/opengl/qopenglextensions_p.h676
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp1354
-rw-r--r--src/gui/opengl/qopenglframebufferobject.h158
-rw-r--r--src/gui/opengl/qopenglframebufferobject_p.h164
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp2452
-rw-r--r--src/gui/opengl/qopenglfunctions.h2427
-rw-r--r--src/gui/opengl/qopenglgradientcache.cpp227
-rw-r--r--src/gui/opengl/qopenglgradientcache_p.h101
-rw-r--r--src/gui/opengl/qopenglpaintdevice.cpp153
-rw-r--r--src/gui/opengl/qopenglpaintdevice_p.h119
-rw-r--r--src/gui/opengl/qopenglshadercache_meego_p.h457
-rw-r--r--src/gui/opengl/qopenglshadercache_p.h (renamed from src/opengl/util/meego/main.cpp)77
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp3171
-rw-r--r--src/gui/opengl/qopenglshaderprogram.h317
-rw-r--r--src/gui/opengl/qpaintengineex_opengl2.cpp2454
-rw-r--r--src/gui/opengl/qpaintengineex_opengl2_p.h338
-rw-r--r--src/gui/opengl/qrbtree_p.h573
-rw-r--r--src/gui/opengl/qtextureglyphcache_gl.cpp396
-rw-r--r--src/gui/opengl/qtextureglyphcache_gl_p.h169
-rw-r--r--src/gui/opengl/qtriangulatingstroker.cpp588
-rw-r--r--src/gui/opengl/qtriangulatingstroker_p.h157
-rw-r--r--src/gui/opengl/qtriangulator.cpp2622
-rw-r--r--src/gui/opengl/qtriangulator_p.h148
-rw-r--r--src/gui/painting/qpaintengine.cpp2
-rw-r--r--src/gui/painting/qpaintengineex_p.h2
-rw-r--r--src/gui/painting/qpainter.cpp2
-rw-r--r--src/gui/text/qfont.h2
-rw-r--r--src/gui/text/qglyphrun.h6
-rw-r--r--src/gui/text/qglyphrun_p.h6
-rw-r--r--src/gui/text/qstatictext.cpp2
-rw-r--r--src/modules/qt_gui.pri1
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp18
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp8
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache_p.h6
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h10
-rw-r--r--src/opengl/gl2paintengineex/qtriangulator_p.h10
-rw-r--r--src/opengl/qgl.cpp22
-rw-r--r--src/opengl/qgl.h6
-rw-r--r--src/opengl/qgl_p.h18
-rw-r--r--src/opengl/qgl_qpa.cpp20
-rw-r--r--src/opengl/qglbuffer.cpp4
-rw-r--r--src/opengl/qglextensions_p.h4
-rw-r--r--src/opengl/qglframebufferobject.cpp4
-rw-r--r--src/opengl/qglfunctions.cpp14
-rw-r--r--src/opengl/qglpixelbuffer.cpp4
-rw-r--r--src/opengl/qglshaderprogram.cpp7
-rw-r--r--src/opengl/util/README-GLSL18
-rw-r--r--src/opengl/util/brush_painter.glsl7
-rw-r--r--src/opengl/util/brushes.conf6
-rw-r--r--src/opengl/util/composition_mode_colorburn.glsl13
-rw-r--r--src/opengl/util/composition_mode_colordodge.glsl15
-rw-r--r--src/opengl/util/composition_mode_darken.glsl9
-rw-r--r--src/opengl/util/composition_mode_difference.glsl9
-rw-r--r--src/opengl/util/composition_mode_exclusion.glsl9
-rw-r--r--src/opengl/util/composition_mode_hardlight.glsl14
-rw-r--r--src/opengl/util/composition_mode_lighten.glsl9
-rw-r--r--src/opengl/util/composition_mode_multiply.glsl9
-rw-r--r--src/opengl/util/composition_mode_overlay.glsl13
-rw-r--r--src/opengl/util/composition_mode_screen.glsl6
-rw-r--r--src/opengl/util/composition_mode_softlight.glsl22
-rw-r--r--src/opengl/util/composition_modes.conf12
-rw-r--r--src/opengl/util/conical_brush.glsl27
-rw-r--r--src/opengl/util/ellipse_aa.glsl58
-rw-r--r--src/opengl/util/fast_painter.glsl19
-rw-r--r--src/opengl/util/fragmentprograms_p.h7287
-rw-r--r--src/opengl/util/generator.cpp500
-rw-r--r--src/opengl/util/generator.pro13
-rwxr-xr-xsrc/opengl/util/glsl_to_include.sh73
-rw-r--r--src/opengl/util/linear_brush.glsl22
-rw-r--r--src/opengl/util/masks.conf2
-rw-r--r--src/opengl/util/meego/shader-cache-introspector.pro7
-rw-r--r--src/opengl/util/painter.glsl21
-rw-r--r--src/opengl/util/painter_nomask.glsl9
-rw-r--r--src/opengl/util/pattern_brush.glsl23
-rw-r--r--src/opengl/util/radial_brush.glsl28
-rw-r--r--src/opengl/util/simple_porter_duff.glsl16
-rw-r--r--src/opengl/util/solid_brush.glsl4
-rw-r--r--src/opengl/util/texture_brush.glsl21
-rw-r--r--src/opengl/util/trap_exact_aa.glsl58
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm2
-rw-r--r--src/plugins/platforms/directfb/qdirectfbglcontext.cpp4
-rw-r--r--src/plugins/platforms/directfb/qdirectfbglcontext.h4
-rw-r--r--src/plugins/platforms/directfb/qdirectfbwindow.cpp1
-rw-r--r--src/plugins/platforms/eglfs/qeglfsbackingstore.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp4
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h6
-rw-r--r--src/plugins/platforms/kms/qkmscontext.cpp4
-rw-r--r--src/plugins/platforms/kms/qkmscontext.h4
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.cpp4
-rw-r--r--src/plugins/platforms/kms/qkmsintegration.h2
-rw-r--r--src/plugins/platforms/openkode/qopenkodeintegration.h2
-rw-r--r--src/plugins/platforms/openkode/qopenkodewindow.cpp2
-rw-r--r--src/plugins/platforms/openkode/qopenkodewindow.h2
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdglcontext.cpp2
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdglcontext.h4
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdintegration.cpp4
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdintegration.h2
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdnativeinterface.cpp4
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdnativeinterface.h4
-rw-r--r--src/plugins/platforms/uikit/quikitwindow.h2
-rw-r--r--src/plugins/platforms/uikit/quikitwindow.mm10
-rw-r--r--src/plugins/platforms/wayland/gl_integration/qwaylandglintegration.h4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_cgl/qwaylandreadbackcglcontext.cpp8
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_cgl/qwaylandreadbackcglcontext.h6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_cgl/qwaylandreadbackcglintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_cgl/qwaylandreadbackcglintegration.h2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglcontext.h4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglintegration.h2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_egl/qwaylandreadbackeglwindow.h2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.cpp8
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxcontext.h6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/readback_glx/qwaylandreadbackglxintegration.h2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandeglintegration.h2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.cpp6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/wayland_egl/qwaylandglcontext.h6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglcontext.h4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_egl/qwaylandxcompositeeglintegration.h4
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxcontext.h6
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.cpp2
-rw-r--r--src/plugins/platforms/wayland/gl_integration/xcomposite_glx/qwaylandxcompositeglxintegration.h2
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.cpp6
-rw-r--r--src/plugins/platforms/wayland/qwaylandintegration.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qdri2context.cpp4
-rw-r--r--src/plugins/platforms/xcb/qdri2context.h4
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h6
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h4
-rw-r--r--src/plugins/platforms/xlib/qglxintegration.cpp6
-rw-r--r--src/plugins/platforms/xlib/qglxintegration.h6
-rw-r--r--src/plugins/platforms/xlib/qxlibintegration.cpp2
-rw-r--r--src/plugins/platforms/xlib/qxlibintegration.h2
-rw-r--r--src/plugins/platforms/xlib/qxlibwindow.h2
-rw-r--r--src/tools/uic/qclass_lib_map.h2
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp4
197 files changed, 24066 insertions, 8999 deletions
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index 9b0d82e69f..e0c02aa150 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience of
-// the QtOpenGL and QtOpenVG modules. This header file may change from
+// the QtGui and QtOpenVG modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/egl/qegl_qpa.cpp b/src/gui/egl/qegl_qpa.cpp
index 167a65bab5..c3eb044b22 100644
--- a/src/gui/egl/qegl_qpa.cpp
+++ b/src/gui/egl/qegl_qpa.cpp
@@ -94,7 +94,7 @@ void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
if (!dev)
return;
- // Find the QGLScreen for this paint device.
+ // Find the QOpenGLScreen for this paint device.
QPlatformScreen *screen = screenForDevice(dev);
if (!screen)
return;
diff --git a/src/gui/egl/qeglcontext_p.h b/src/gui/egl/qeglcontext_p.h
index 16da430130..7ea18627d1 100644
--- a/src/gui/egl/qeglcontext_p.h
+++ b/src/gui/egl/qeglcontext_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience of
-// the QtOpenGL and QtOpenVG modules. This header file may change from
+// the QtGui and QtOpenVG modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/egl/qeglproperties_p.h b/src/gui/egl/qeglproperties_p.h
index 2d03cd0494..d8d64e01a1 100644
--- a/src/gui/egl/qeglproperties_p.h
+++ b/src/gui/egl/qeglproperties_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QtOpenGL and QtOpenVG modules. This header file may change from
+// of the QtGui and QtOpenVG modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index f1d5bbaea5..4ee9d764ec 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -21,6 +21,7 @@ include(text/text.pri)
include(painting/painting.pri)
include(util/util.pri)
include(math3d/math3d.pri)
+include(opengl/opengl.pri)
include(egl/egl.pri)
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 402708b48c..330370e25b 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -182,7 +182,7 @@ private:
friend class QBitmap;
friend class QPaintDevice;
friend class QPainter;
- friend class QGLWidget;
+ friend class QOpenGLWidget;
friend class QWidgetPrivate;
friend class QRasterBuffer;
#if !defined(QT_NO_DATASTREAM)
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index 7fb1bd6530..a214f397ed 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -73,7 +73,7 @@ QPlatformPixmap::QPlatformPixmap(PixelType pixelType, int objectId)
QPlatformPixmap::~QPlatformPixmap()
{
// Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
- // then set is_cached to false. For example, on X11 QtOpenGL needs to delete the GLXPixmap
+ // then set is_cached to false. For example, on X11 QtGui needs to delete the GLXPixmap
// or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
// otherwise some drivers will leak the GL surface. In this case, QX11PlatformPixmap will
// call the cleanup hooks itself before deleting the native pixmap and set is_cached to
diff --git a/src/gui/image/qplatformpixmap_qpa.h b/src/gui/image/qplatformpixmap_qpa.h
index 5f5b903962..d528f4138f 100644
--- a/src/gui/image/qplatformpixmap_qpa.h
+++ b/src/gui/image/qplatformpixmap_qpa.h
@@ -136,7 +136,7 @@ protected:
private:
friend class QPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
- friend class QGLTextureCache; //Needs to check the reference count
+ friend class QOpenGLTextureCache; //Needs to check the reference count
friend class QExplicitlySharedDataPointer<QPlatformPixmap>;
QAtomicInt ref;
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 44d039512f..b24d51c17d 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -49,9 +49,9 @@ qpa {
kernel/qplatformintegrationfactory_qpa_p.h \
kernel/qplatformintegrationplugin_qpa.h \
kernel/qplatformwindow_qpa.h \
- kernel/qplatformglcontext_qpa.h \
- kernel/qguiglcontext_qpa.h \
- kernel/qguiglcontext_qpa_p.h \
+ kernel/qplatformopenglcontext_qpa.h \
+ kernel/qopenglcontext.h \
+ kernel/qopenglcontext_p.h \
kernel/qplatformcursor_qpa.h \
kernel/qplatformclipboard_qpa.h \
kernel/qplatformnativeinterface_qpa.h \
@@ -73,8 +73,8 @@ qpa {
kernel/qplatformintegrationfactory_qpa.cpp \
kernel/qplatformintegrationplugin_qpa.cpp \
kernel/qplatformwindow_qpa.cpp \
- kernel/qplatformglcontext_qpa.cpp \
- kernel/qguiglcontext_qpa.cpp \
+ kernel/qplatformopenglcontext_qpa.cpp \
+ kernel/qopenglcontext.cpp \
kernel/qplatformcursor_qpa.cpp \
kernel/qplatformclipboard_qpa.cpp \
kernel/qplatformnativeinterface_qpa.cpp \
diff --git a/src/gui/kernel/qguiglcontext_qpa_p.h b/src/gui/kernel/qguiglcontext_qpa_p.h
deleted file mode 100644
index a9c8f5c75e..0000000000
--- a/src/gui/kernel/qguiglcontext_qpa_p.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QGUIGLCONTEXT_P_H
-#define QGUIGLCONTEXT_P_H
-
-#include "qguiglcontext_qpa.h"
-#include <private/qobject_p.h>
-#include <qmutex.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Gui)
-
-class QGuiGLContext;
-class QGLMultiGroupSharedResource;
-
-class Q_GUI_EXPORT QGLSharedResource
-{
-public:
- QGLSharedResource(QGuiGLContextGroup *group);
- virtual ~QGLSharedResource() = 0;
-
- QGuiGLContextGroup *group() const { return m_group; }
-
- // schedule the resource for deletion at an appropriate time
- void free();
-
-protected:
- // the resource's share group no longer exists, invalidate the resource
- virtual void invalidateResource() = 0;
-
- // a valid context in the group is current, free the resource
- virtual void freeResource(QGuiGLContext *context) = 0;
-
-private:
- QGuiGLContextGroup *m_group;
-
- friend class QGuiGLContextGroup;
- friend class QGuiGLContextGroupPrivate;
-
- Q_DISABLE_COPY(QGLSharedResource);
-};
-
-class Q_GUI_EXPORT QGuiGLContextGroupPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QGuiGLContextGroup);
-public:
- QGuiGLContextGroupPrivate()
- : m_context(0)
- , m_mutex(QMutex::Recursive)
- , m_refs(0)
- {
- }
-
- void addContext(QGuiGLContext *ctx);
- void removeContext(QGuiGLContext *ctx);
-
- void deletePendingResources(QGuiGLContext *ctx);
-
- QGuiGLContext *m_context;
-
- QList<QGuiGLContext *> m_shares;
- QMutex m_mutex;
-
- QHash<QGLMultiGroupSharedResource *, QGLSharedResource *> m_resources;
- QAtomicInt m_refs;
-
- QList<QGLSharedResource *> m_sharedResources;
- QList<QGLSharedResource *> m_pendingDeletion;
-
- void cleanupResources(QGuiGLContext *ctx);
-};
-
-class Q_GUI_EXPORT QGLMultiGroupSharedResource
-{
-public:
- QGLMultiGroupSharedResource();
- ~QGLMultiGroupSharedResource();
-
- void insert(QGuiGLContext *context, QGLSharedResource *value);
- void cleanup(QGuiGLContext *context);
- void cleanup(QGuiGLContext *context, QGLSharedResource *value);
-
- QGLSharedResource *value(QGuiGLContext *context);
-
- template <typename T>
- T *value(QGuiGLContext *context) {
- QGuiGLContextGroup *group = context->shareGroup();
- T *resource = static_cast<T *>(group->d_func()->m_resources.value(this, 0));
- if (!resource) {
- resource = new T(context);
- insert(context, resource);
- }
- return resource;
- }
-
-private:
- QAtomicInt active;
- QList<QGuiGLContextGroup *> m_groups;
-};
-
-class Q_GUI_EXPORT QGuiGLContextPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QGuiGLContext);
-public:
- QGuiGLContextPrivate()
- : qGLContextHandle(0)
- , platformGLContext(0)
- , shareContext(0)
- , shareGroup(0)
- , screen(0)
- , surface(0)
- {
- }
-
- virtual ~QGuiGLContextPrivate()
- {
- //do not delete the QGLContext handle here as it is deleted in
- //QWidgetPrivate::deleteTLSysExtra()
- }
- void *qGLContextHandle;
- void (*qGLContextDeleteFunction)(void *handle);
-
- QSurfaceFormat requestedFormat;
- QPlatformGLContext *platformGLContext;
- QGuiGLContext *shareContext;
- QGuiGLContextGroup *shareGroup;
- QScreen *screen;
- QSurface *surface;
-
- QHash<QGLMultiGroupSharedResource *, void *> m_resources;
-
- static void setCurrentContext(QGuiGLContext *context);
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QGUIGLCONTEXT_P_H
diff --git a/src/gui/kernel/qguiglcontext_qpa.cpp b/src/gui/kernel/qopenglcontext.cpp
index 71c830174e..92a651ddf4 100644
--- a/src/gui/kernel/qguiglcontext_qpa.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,9 +39,9 @@
**
****************************************************************************/
-#include "qplatformglcontext_qpa.h"
-#include "qguiglcontext_qpa.h"
-#include "qguiglcontext_qpa_p.h"
+#include "qplatformopenglcontext_qpa.h"
+#include "qopenglcontext.h"
+#include "qopenglcontext_p.h"
#include "qwindow.h"
#include <QtCore/QThreadStorage>
@@ -50,6 +50,8 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QScreen>
+#include <private/qopenglextensions_p.h>
+
#include <QDebug>
class QGuiGLThreadContext
@@ -59,12 +61,12 @@ public:
if (context)
context->doneCurrent();
}
- QGuiGLContext *context;
+ QOpenGLContext *context;
};
static QThreadStorage<QGuiGLThreadContext *> qwindow_context_storage;
-void QGuiGLContextPrivate::setCurrentContext(QGuiGLContext *context)
+void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
{
QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
if (!threadContext) {
@@ -81,7 +83,7 @@ void QGuiGLContextPrivate::setCurrentContext(QGuiGLContext *context)
/*!
Returns the last context which called makeCurrent. This function is thread aware.
*/
-QGuiGLContext* QGuiGLContext::currentContext()
+QOpenGLContext* QOpenGLContext::currentContext()
{
QGuiGLThreadContext *threadContext = qwindow_context_storage.localData();
if(threadContext) {
@@ -90,20 +92,20 @@ QGuiGLContext* QGuiGLContext::currentContext()
return 0;
}
-bool QGuiGLContext::areSharing(QGuiGLContext *first, QGuiGLContext *second)
+bool QOpenGLContext::areSharing(QOpenGLContext *first, QOpenGLContext *second)
{
return first->shareGroup() == second->shareGroup();
}
-QPlatformGLContext *QGuiGLContext::handle() const
+QPlatformOpenGLContext *QOpenGLContext::handle() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->platformGLContext;
}
-QPlatformGLContext *QGuiGLContext::shareHandle() const
+QPlatformOpenGLContext *QOpenGLContext::shareHandle() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
if (d->shareContext)
return d->shareContext->handle();
return 0;
@@ -112,37 +114,37 @@ QPlatformGLContext *QGuiGLContext::shareHandle() const
/*!
Creates a new GL context instance, you need to call create() before it can be used.
*/
-QGuiGLContext::QGuiGLContext()
- : QObject(*new QGuiGLContextPrivate())
+QOpenGLContext::QOpenGLContext(QObject *parent)
+ : QObject(*new QOpenGLContextPrivate(), parent)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
d->screen = QGuiApplication::primaryScreen();
}
/*!
Sets the format the GL context should be compatible with. You need to call create() before it takes effect.
*/
-void QGuiGLContext::setFormat(const QSurfaceFormat &format)
+void QOpenGLContext::setFormat(const QSurfaceFormat &format)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
d->requestedFormat = format;
}
/*!
Sets the context to share textures, shaders, and other GL resources with. You need to call create() before it takes effect.
*/
-void QGuiGLContext::setShareContext(QGuiGLContext *shareContext)
+void QOpenGLContext::setShareContext(QOpenGLContext *shareContext)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
d->shareContext = shareContext;
}
/*!
Sets the screen the GL context should be valid for. You need to call create() before it takes effect.
*/
-void QGuiGLContext::setScreen(QScreen *screen)
+void QOpenGLContext::setScreen(QScreen *screen)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
d->screen = screen;
if (!d->screen)
d->screen = QGuiApplication::primaryScreen();
@@ -153,34 +155,36 @@ void QGuiGLContext::setScreen(QScreen *screen)
Returns true if the native context was successfully created and is ready to be used.
*/
-bool QGuiGLContext::create()
+bool QOpenGLContext::create()
{
destroy();
- Q_D(QGuiGLContext);
- d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformGLContext(this);
+ Q_D(QOpenGLContext);
+ d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this);
d->platformGLContext->setContext(this);
- d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QGuiGLContextGroup;
+ d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup;
d->shareGroup->d_func()->addContext(this);
return d->platformGLContext;
}
-void QGuiGLContext::destroy()
+void QOpenGLContext::destroy()
{
- Q_D(QGuiGLContext);
- if (QGuiGLContext::currentContext() == this)
+ Q_D(QOpenGLContext);
+ if (QOpenGLContext::currentContext() == this)
doneCurrent();
if (d->shareGroup)
d->shareGroup->d_func()->removeContext(this);
d->shareGroup = 0;
delete d->platformGLContext;
d->platformGLContext = 0;
+ delete d->functions;
+ d->functions = 0;
}
/*!
If this is the current context for the thread, doneCurrent is called
*/
-QGuiGLContext::~QGuiGLContext()
+QOpenGLContext::~QOpenGLContext()
{
destroy();
}
@@ -188,18 +192,32 @@ QGuiGLContext::~QGuiGLContext()
/*!
Returns if this context is valid, i.e. has been successfully created.
*/
-bool QGuiGLContext::isValid() const
+bool QOpenGLContext::isValid() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->platformGLContext != 0;
}
/*!
+ Get the QOpenGLFunctions instance for this context.
+
+ The context or a sharing context must be current.
+*/
+
+QOpenGLFunctions *QOpenGLContext::functions() const
+{
+ Q_D(const QOpenGLContext);
+ if (!d->functions)
+ const_cast<QOpenGLFunctions *&>(d->functions) = new QOpenGLExtensions(QOpenGLContext::currentContext());
+ return d->functions;
+}
+
+/*!
If surface is 0 this is equivalent to calling doneCurrent().
*/
-bool QGuiGLContext::makeCurrent(QSurface *surface)
+bool QOpenGLContext::makeCurrent(QSurface *surface)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
if (!d->platformGLContext)
return false;
@@ -212,7 +230,7 @@ bool QGuiGLContext::makeCurrent(QSurface *surface)
return false;
if (d->platformGLContext->makeCurrent(surface->surfaceHandle())) {
- QGuiGLContextPrivate::setCurrentContext(this);
+ QOpenGLContextPrivate::setCurrentContext(this);
d->surface = surface;
d->shareGroup->d_func()->deletePendingResources(this);
@@ -226,17 +244,17 @@ bool QGuiGLContext::makeCurrent(QSurface *surface)
/*!
Convenience function for calling makeCurrent with a 0 surface.
*/
-void QGuiGLContext::doneCurrent()
+void QOpenGLContext::doneCurrent()
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
if (!d->platformGLContext)
return;
- if (QGuiGLContext::currentContext() == this)
+ if (QOpenGLContext::currentContext() == this)
d->shareGroup->d_func()->deletePendingResources(this);
d->platformGLContext->doneCurrent();
- QGuiGLContextPrivate::setCurrentContext(0);
+ QOpenGLContextPrivate::setCurrentContext(0);
d->surface = 0;
}
@@ -244,58 +262,58 @@ void QGuiGLContext::doneCurrent()
/*!
Returns the surface the context is current for.
*/
-QSurface *QGuiGLContext::surface() const
+QSurface *QOpenGLContext::surface() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->surface;
}
-void QGuiGLContext::swapBuffers(QSurface *surface)
+void QOpenGLContext::swapBuffers(QSurface *surface)
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
if (!d->platformGLContext)
return;
if (!surface) {
- qWarning() << "QGuiGLContext::swapBuffers() called with null argument";
+ qWarning() << "QOpenGLContext::swapBuffers() called with null argument";
return;
}
d->platformGLContext->swapBuffers(surface->surfaceHandle());
}
-void (*QGuiGLContext::getProcAddress(const QByteArray &procName)) ()
+void (*QOpenGLContext::getProcAddress(const QByteArray &procName)) ()
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
if (!d->platformGLContext)
return 0;
return d->platformGLContext->getProcAddress(procName);
}
-QSurfaceFormat QGuiGLContext::format() const
+QSurfaceFormat QOpenGLContext::format() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
if (!d->platformGLContext)
return d->requestedFormat;
return d->platformGLContext->format();
}
-QGuiGLContextGroup *QGuiGLContext::shareGroup() const
+QOpenGLContextGroup *QOpenGLContext::shareGroup() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->shareGroup;
}
-QGuiGLContext *QGuiGLContext::shareContext() const
+QOpenGLContext *QOpenGLContext::shareContext() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->shareContext;
}
-QScreen *QGuiGLContext::screen() const
+QScreen *QOpenGLContext::screen() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->screen;
}
@@ -303,22 +321,22 @@ QScreen *QGuiGLContext::screen() const
internal: Needs to have a pointer to qGLContext. But since this is in QtGui we cant
have any type information.
*/
-void *QGuiGLContext::qGLContextHandle() const
+void *QOpenGLContext::qGLContextHandle() const
{
- Q_D(const QGuiGLContext);
+ Q_D(const QOpenGLContext);
return d->qGLContextHandle;
}
-void QGuiGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))
+void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *))
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
d->qGLContextHandle = handle;
d->qGLContextDeleteFunction = qGLContextDeleteFunction;
}
-void QGuiGLContext::deleteQGLContext()
+void QOpenGLContext::deleteQGLContext()
{
- Q_D(QGuiGLContext);
+ Q_D(QOpenGLContext);
if (d->qGLContextDeleteFunction && d->qGLContextHandle) {
d->qGLContextDeleteFunction(d->qGLContextHandle);
d->qGLContextDeleteFunction = 0;
@@ -326,17 +344,17 @@ void QGuiGLContext::deleteQGLContext()
}
}
-QGuiGLContextGroup::QGuiGLContextGroup()
- : QObject(*new QGuiGLContextGroupPrivate())
+QOpenGLContextGroup::QOpenGLContextGroup()
+ : QObject(*new QOpenGLContextGroupPrivate())
{
}
-QGuiGLContextGroup::~QGuiGLContextGroup()
+QOpenGLContextGroup::~QOpenGLContextGroup()
{
- Q_D(QGuiGLContextGroup);
+ Q_D(QOpenGLContextGroup);
- QList<QGLSharedResource *>::iterator it = d->m_sharedResources.begin();
- QList<QGLSharedResource *>::iterator end = d->m_sharedResources.end();
+ QList<QOpenGLSharedResource *>::iterator it = d->m_sharedResources.begin();
+ QList<QOpenGLSharedResource *>::iterator end = d->m_sharedResources.end();
while (it != end) {
(*it)->invalidateResource();
@@ -347,28 +365,28 @@ QGuiGLContextGroup::~QGuiGLContextGroup()
qDeleteAll(d->m_pendingDeletion.begin(), d->m_pendingDeletion.end());
}
-QList<QGuiGLContext *> QGuiGLContextGroup::shares() const
+QList<QOpenGLContext *> QOpenGLContextGroup::shares() const
{
- Q_D(const QGuiGLContextGroup);
+ Q_D(const QOpenGLContextGroup);
return d->m_shares;
}
-QGuiGLContextGroup *QGuiGLContextGroup::currentContextGroup()
+QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup()
{
- QGuiGLContext *current = QGuiGLContext::currentContext();
+ QOpenGLContext *current = QOpenGLContext::currentContext();
return current ? current->shareGroup() : 0;
}
-void QGuiGLContextGroupPrivate::addContext(QGuiGLContext *ctx)
+void QOpenGLContextGroupPrivate::addContext(QOpenGLContext *ctx)
{
QMutexLocker locker(&m_mutex);
m_refs.ref();
m_shares << ctx;
}
-void QGuiGLContextGroupPrivate::removeContext(QGuiGLContext *ctx)
+void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
{
- Q_Q(QGuiGLContextGroup);
+ Q_Q(QOpenGLContextGroup);
QMutexLocker locker(&m_mutex);
m_shares.removeOne(ctx);
@@ -380,33 +398,35 @@ void QGuiGLContextGroupPrivate::removeContext(QGuiGLContext *ctx)
q->deleteLater();
}
-void QGuiGLContextGroupPrivate::deletePendingResources(QGuiGLContext *ctx)
+void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
{
QMutexLocker locker(&m_mutex);
- QList<QGLSharedResource *>::iterator it = m_pendingDeletion.begin();
- QList<QGLSharedResource *>::iterator end = m_pendingDeletion.end();
+ QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
+ m_pendingDeletion.clear();
+
+ QList<QOpenGLSharedResource *>::iterator it = pending.begin();
+ QList<QOpenGLSharedResource *>::iterator end = pending.end();
while (it != end) {
(*it)->freeResource(ctx);
delete *it;
++it;
}
- m_pendingDeletion.clear();
}
-QGLSharedResource::QGLSharedResource(QGuiGLContextGroup *group)
+QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group)
: m_group(group)
{
QMutexLocker locker(&m_group->d_func()->m_mutex);
m_group->d_func()->m_sharedResources << this;
}
-QGLSharedResource::~QGLSharedResource()
+QOpenGLSharedResource::~QOpenGLSharedResource()
{
}
// schedule the resource for deletion at an appropriate time
-void QGLSharedResource::free()
+void QOpenGLSharedResource::free()
{
if (!m_group) {
delete this;
@@ -418,13 +438,22 @@ void QGLSharedResource::free()
m_group->d_func()->m_pendingDeletion << this;
// can we delete right away?
- QGuiGLContext *current = QGuiGLContext::currentContext();
+ QOpenGLContext *current = QOpenGLContext::currentContext();
if (current && current->shareGroup() == m_group) {
m_group->d_func()->deletePendingResources(current);
}
}
-QGLMultiGroupSharedResource::QGLMultiGroupSharedResource()
+void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context)
+{
+ if (m_id) {
+ QOpenGLFunctions functions(context);
+ m_func(&functions, m_id);
+ m_id = 0;
+ }
+}
+
+QOpenGLMultiGroupSharedResource::QOpenGLMultiGroupSharedResource()
: active(0)
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
@@ -432,61 +461,63 @@ QGLMultiGroupSharedResource::QGLMultiGroupSharedResource()
#endif
}
-QGLMultiGroupSharedResource::~QGLMultiGroupSharedResource()
+QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size());
#endif
for (int i = 0; i < m_groups.size(); ++i) {
- QGuiGLContext *context = m_groups.at(i)->shares().first();
- QGLSharedResource *resource = value(context);
- if (resource)
- resource->free();
+ if (!m_groups.at(i)->shares().isEmpty()) {
+ QOpenGLContext *context = m_groups.at(i)->shares().first();
+ QOpenGLSharedResource *resource = value(context);
+ if (resource)
+ resource->free();
+ }
m_groups.at(i)->d_func()->m_resources.remove(this);
active.deref();
}
#ifndef QT_NO_DEBUG
if (active != 0) {
- qWarning("QtOpenGL: Resources are still available at program shutdown.\n"
- " This is possibly caused by a leaked QGLWidget, \n"
- " QGLFramebufferObject or QGLPixelBuffer.");
+ qWarning("QtGui: Resources are still available at program shutdown.\n"
+ " This is possibly caused by a leaked QOpenGLWidget, \n"
+ " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
}
#endif
}
-void QGLMultiGroupSharedResource::insert(QGuiGLContext *context, QGLSharedResource *value)
+void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this);
#endif
- QGuiGLContextGroup *group = context->shareGroup();
+ QOpenGLContextGroup *group = context->shareGroup();
Q_ASSERT(!group->d_func()->m_resources.contains(this));
group->d_func()->m_resources.insert(this, value);
m_groups.append(group);
active.ref();
}
-QGLSharedResource *QGLMultiGroupSharedResource::value(QGuiGLContext *context)
+QOpenGLSharedResource *QOpenGLMultiGroupSharedResource::value(QOpenGLContext *context)
{
- QGuiGLContextGroup *group = context->shareGroup();
+ QOpenGLContextGroup *group = context->shareGroup();
return group->d_func()->m_resources.value(this, 0);
}
-void QGLMultiGroupSharedResource::cleanup(QGuiGLContext *ctx)
+void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx)
{
- QGLSharedResource *resource = value(ctx);
+ QOpenGLSharedResource *resource = value(ctx);
if (resource != 0) {
resource->free();
- QGuiGLContextGroup *group = ctx->shareGroup();
+ QOpenGLContextGroup *group = ctx->shareGroup();
group->d_func()->m_resources.remove(this);
m_groups.removeOne(group);
active.deref();
}
}
-void QGLMultiGroupSharedResource::cleanup(QGuiGLContext *ctx, QGLSharedResource *value)
+void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx, QOpenGLSharedResource *value)
{
#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread());
@@ -494,7 +525,7 @@ void QGLMultiGroupSharedResource::cleanup(QGuiGLContext *ctx, QGLSharedResource
value->free();
active.deref();
- QGuiGLContextGroup *group = ctx->shareGroup();
+ QOpenGLContextGroup *group = ctx->shareGroup();
m_groups.removeOne(group);
}
diff --git a/src/gui/kernel/qguiglcontext_qpa.h b/src/gui/kernel/qopenglcontext.h
index a234bd3cb6..cf334709ec 100644
--- a/src/gui/kernel/qguiglcontext_qpa.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,13 +39,13 @@
**
****************************************************************************/
-#ifndef QGUIGLCONTEXT_H
-#define QGUIGLCONTEXT_H
+#ifndef QOPENGLCONTEXT_H
+#define QOPENGLCONTEXT_H
#include <QtCore/qnamespace.h>
#include <QtCore/QScopedPointer>
-#include <QSurfaceFormat>
+#include <QtGui/QSurfaceFormat>
QT_BEGIN_HEADER
@@ -53,49 +53,52 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-class QGuiGLContextPrivate;
-class QGuiGLContextGroupPrivate;
-class QPlatformGLContext;
+class QOpenGLContextPrivate;
+class QOpenGLContextGroupPrivate;
+class QOpenGLFunctions;
+class QPlatformOpenGLContext;
+
+class QScreen;
class QSurface;
-class Q_GUI_EXPORT QGuiGLContextGroup : public QObject
+class Q_GUI_EXPORT QOpenGLContextGroup : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QGuiGLContextGroup)
+ Q_DECLARE_PRIVATE(QOpenGLContextGroup)
public:
- ~QGuiGLContextGroup();
+ ~QOpenGLContextGroup();
- QList<QGuiGLContext *> shares() const;
+ QList<QOpenGLContext *> shares() const;
- static QGuiGLContextGroup *currentContextGroup();
+ static QOpenGLContextGroup *currentContextGroup();
private:
- QGuiGLContextGroup();
+ QOpenGLContextGroup();
- friend class QGuiGLContext;
- friend class QGLContextGroupResourceBase;
- friend class QGLSharedResource;
- friend class QGLMultiGroupSharedResource;
+ friend class QOpenGLContext;
+ friend class QOpenGLContextGroupResourceBase;
+ friend class QOpenGLSharedResource;
+ friend class QOpenGLMultiGroupSharedResource;
};
-class Q_GUI_EXPORT QGuiGLContext : public QObject
+class Q_GUI_EXPORT QOpenGLContext : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QGuiGLContext);
+ Q_DECLARE_PRIVATE(QOpenGLContext);
public:
- QGuiGLContext();
- ~QGuiGLContext();
+ QOpenGLContext(QObject *parent = 0);
+ ~QOpenGLContext();
void setFormat(const QSurfaceFormat &format);
- void setShareContext(QGuiGLContext *shareContext);
+ void setShareContext(QOpenGLContext *shareContext);
void setScreen(QScreen *screen);
bool create();
bool isValid() const;
QSurfaceFormat format() const;
- QGuiGLContext *shareContext() const;
- QGuiGLContextGroup *shareGroup() const;
+ QOpenGLContext *shareContext() const;
+ QOpenGLContextGroup *shareGroup() const;
QScreen *screen() const;
bool makeCurrent(QSurface *surface);
@@ -106,16 +109,26 @@ public:
QSurface *surface() const;
- static QGuiGLContext *currentContext();
- static bool areSharing(QGuiGLContext *first, QGuiGLContext *second);
+ static QOpenGLContext *currentContext();
+ static bool areSharing(QOpenGLContext *first, QOpenGLContext *second);
+
+ QPlatformOpenGLContext *handle() const;
+ QPlatformOpenGLContext *shareHandle() const;
- QPlatformGLContext *handle() const;
- QPlatformGLContext *shareHandle() const;
+ QOpenGLFunctions *functions() const;
private:
- //hack to make it work with QGLContext::CurrentContext
friend class QGLContext;
- friend class QGLContextResourceBase;
+ friend class QOpenGLContextResourceBase;
+ friend class QOpenGLPaintDevice;
+ friend class QOpenGLGlyphTexture;
+ friend class QOpenGLTextureGlyphCache;
+ friend class QOpenGLEngineShaderManager;
+ friend class QOpenGLFramebufferObject;
+ friend class QOpenGLFramebufferObjectPrivate;
+ friend class QOpenGL2PaintEngineEx;
+ friend class QOpenGL2PaintEngineExPrivate;
+ friend class QSGDistanceFieldGlyphCache;
friend class QWidgetPrivate;
void *qGLContextHandle() const;
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
new file mode 100644
index 0000000000..61cfbf9563
--- /dev/null
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGUIGLCONTEXT_P_H
+#define QGUIGLCONTEXT_P_H
+
+#include "qopengl.h"
+#include "qopenglcontext.h"
+#include <private/qobject_p.h>
+#include <qmutex.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QOpenGLFunctions;
+class QOpenGLContext;
+class QOpenGLMultiGroupSharedResource;
+
+class Q_GUI_EXPORT QOpenGLSharedResource
+{
+public:
+ QOpenGLSharedResource(QOpenGLContextGroup *group);
+ virtual ~QOpenGLSharedResource() = 0;
+
+ QOpenGLContextGroup *group() const { return m_group; }
+
+ // schedule the resource for deletion at an appropriate time
+ void free();
+
+protected:
+ // the resource's share group no longer exists, invalidate the resource
+ virtual void invalidateResource() = 0;
+
+ // a valid context in the group is current, free the resource
+ virtual void freeResource(QOpenGLContext *context) = 0;
+
+private:
+ QOpenGLContextGroup *m_group;
+
+ friend class QOpenGLContextGroup;
+ friend class QOpenGLContextGroupPrivate;
+
+ Q_DISABLE_COPY(QOpenGLSharedResource);
+};
+
+class Q_GUI_EXPORT QOpenGLSharedResourceGuard : public QOpenGLSharedResource
+{
+public:
+ typedef void (*FreeResourceFunc)(QOpenGLFunctions *functions, GLuint id);
+ QOpenGLSharedResourceGuard(QOpenGLContext *context, GLuint id, FreeResourceFunc func)
+ : QOpenGLSharedResource(context->shareGroup())
+ , m_id(id)
+ , m_func(func)
+ {
+ }
+
+ GLuint id() const { return m_id; }
+
+protected:
+ void invalidateResource()
+ {
+ m_id = 0;
+ }
+
+ void freeResource(QOpenGLContext *context);
+
+private:
+ GLuint m_id;
+ FreeResourceFunc m_func;
+};
+
+class Q_GUI_EXPORT QOpenGLContextGroupPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLContextGroup);
+public:
+ QOpenGLContextGroupPrivate()
+ : m_context(0)
+ , m_mutex(QMutex::Recursive)
+ , m_refs(0)
+ {
+ }
+
+ void addContext(QOpenGLContext *ctx);
+ void removeContext(QOpenGLContext *ctx);
+
+ void deletePendingResources(QOpenGLContext *ctx);
+
+ QOpenGLContext *m_context;
+
+ QList<QOpenGLContext *> m_shares;
+ QMutex m_mutex;
+
+ QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *> m_resources;
+ QAtomicInt m_refs;
+
+ QList<QOpenGLSharedResource *> m_sharedResources;
+ QList<QOpenGLSharedResource *> m_pendingDeletion;
+
+ void cleanupResources(QOpenGLContext *ctx);
+};
+
+class Q_GUI_EXPORT QOpenGLMultiGroupSharedResource
+{
+public:
+ QOpenGLMultiGroupSharedResource();
+ ~QOpenGLMultiGroupSharedResource();
+
+ void insert(QOpenGLContext *context, QOpenGLSharedResource *value);
+ void cleanup(QOpenGLContext *context);
+ void cleanup(QOpenGLContext *context, QOpenGLSharedResource *value);
+
+ QOpenGLSharedResource *value(QOpenGLContext *context);
+
+ template <typename T>
+ T *value(QOpenGLContext *context) {
+ QOpenGLContextGroup *group = context->shareGroup();
+ T *resource = static_cast<T *>(group->d_func()->m_resources.value(this, 0));
+ if (!resource) {
+ resource = new T(context);
+ insert(context, resource);
+ }
+ return resource;
+ }
+
+private:
+ QAtomicInt active;
+ QList<QOpenGLContextGroup *> m_groups;
+};
+
+class QPaintEngineEx;
+class QOpenGLFunctions;
+
+class Q_GUI_EXPORT QOpenGLContextPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLContext);
+public:
+ QOpenGLContextPrivate()
+ : qGLContextHandle(0)
+ , platformGLContext(0)
+ , shareContext(0)
+ , shareGroup(0)
+ , screen(0)
+ , surface(0)
+ , functions(0)
+ , current_fbo(0)
+ , default_fbo(0)
+ , workaround_brokenFBOReadBack(false)
+ , workaround_brokenTexSubImage(false)
+ , active_engine(0)
+ {
+ }
+
+ virtual ~QOpenGLContextPrivate()
+ {
+ //do not delete the QOpenGLContext handle here as it is deleted in
+ //QWidgetPrivate::deleteTLSysExtra()
+ }
+
+ void *qGLContextHandle;
+ void (*qGLContextDeleteFunction)(void *handle);
+
+ QSurfaceFormat requestedFormat;
+ QPlatformOpenGLContext *platformGLContext;
+ QOpenGLContext *shareContext;
+ QOpenGLContextGroup *shareGroup;
+ QScreen *screen;
+ QSurface *surface;
+ QOpenGLFunctions *functions;
+
+ GLuint current_fbo;
+ GLuint default_fbo;
+
+ bool workaround_brokenFBOReadBack;
+ bool workaround_brokenTexSubImage;
+
+ QPaintEngineEx *active_engine;
+
+ QHash<QOpenGLMultiGroupSharedResource *, void *> m_resources;
+
+ static void setCurrentContext(QOpenGLContext *context);
+
+ int maxTextureSize() const { return 1024; }
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGUIGLCONTEXT_P_H
diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp
index ccbf52bb1e..39341fa88f 100644
--- a/src/gui/kernel/qplatformintegration_qpa.cpp
+++ b/src/gui/kernel/qplatformintegration_qpa.cpp
@@ -192,10 +192,10 @@ QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::Pix
return new QRasterPlatformPixmap(type);
}
-QPlatformGLContext *QPlatformIntegration::createPlatformGLContext(QGuiGLContext *context) const
+QPlatformOpenGLContext *QPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
Q_UNUSED(context);
- qWarning("This plugin does not support createPlatformGLContext!");
+ qWarning("This plugin does not support createPlatformOpenGLContext!");
return 0;
}
diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h
index 97811d45b5..d26fcfabb4 100644
--- a/src/gui/kernel/qplatformintegration_qpa.h
+++ b/src/gui/kernel/qplatformintegration_qpa.h
@@ -59,7 +59,7 @@ class QPlatformFontDatabase;
class QPlatformClipboard;
class QPlatformNativeInterface;
class QPlatformDrag;
-class QPlatformGLContext;
+class QPlatformOpenGLContext;
class QGuiGLFormat;
class QAbstractEventDispatcher;
class QPlatformInputContext;
@@ -80,7 +80,7 @@ public:
virtual QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const;
virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0;
virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0;
- virtual QPlatformGLContext *createPlatformGLContext(QGuiGLContext *context) const;
+ virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const;
// Event dispatcher:
virtual QAbstractEventDispatcher *guiThreadEventDispatcher() const = 0;
diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.cpp b/src/gui/kernel/qplatformnativeinterface_qpa.cpp
index 18bef8a595..20d136e691 100644
--- a/src/gui/kernel/qplatformnativeinterface_qpa.cpp
+++ b/src/gui/kernel/qplatformnativeinterface_qpa.cpp
@@ -50,7 +50,7 @@ void *QPlatformNativeInterface::nativeResourceForWindow(const QByteArray &resour
return 0;
}
-void *QPlatformNativeInterface::nativeResourceForContext(const QByteArray &resource, QGuiGLContext *context)
+void *QPlatformNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
Q_UNUSED(resource);
Q_UNUSED(context);
diff --git a/src/gui/kernel/qplatformnativeinterface_qpa.h b/src/gui/kernel/qplatformnativeinterface_qpa.h
index 136191e2aa..6ea8104fa3 100644
--- a/src/gui/kernel/qplatformnativeinterface_qpa.h
+++ b/src/gui/kernel/qplatformnativeinterface_qpa.h
@@ -50,14 +50,14 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-class QGuiGLContext;
+class QOpenGLContext;
class QWindow;
class QBackingStore;
class Q_GUI_EXPORT QPlatformNativeInterface
{
public:
- virtual void *nativeResourceForContext(const QByteArray &resource, QGuiGLContext *context);
+ virtual void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
virtual void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
virtual void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore);
};
diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformopenglcontext_qpa.cpp
index 5ce7db09e2..2957b4db4b 100644
--- a/src/gui/kernel/qplatformglcontext_qpa.cpp
+++ b/src/gui/kernel/qplatformopenglcontext_qpa.cpp
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,73 +39,73 @@
**
****************************************************************************/
-#include "qplatformglcontext_qpa.h"
+#include "qplatformopenglcontext_qpa.h"
/*!
- \class QPlatformGLContext
+ \class QPlatformOpenGLContext
\since 4.8
\internal
\preliminary
\ingroup qpa
- \brief The QPlatformGLContext class provides an abstraction for native GL contexts.
+ \brief The QPlatformOpenGLContext class provides an abstraction for native GL contexts.
In QPA the way to support OpenGL or OpenVG or other technologies that requires a native GL
- context is through the QPlatformGLContext wrapper.
+ context is through the QPlatformOpenGLContext wrapper.
- There is no factory function for QPlatformGLContexts, but rather only one accessor function.
- The only place to retrieve a QPlatformGLContext from is through a QPlatformWindow.
+ There is no factory function for QPlatformOpenGLContexts, but rather only one accessor function.
+ The only place to retrieve a QPlatformOpenGLContext from is through a QPlatformWindow.
The context which is current for a specific thread can be collected by the currentContext()
- function. This is how QPlatformGLContext also makes it possible to use the QtOpenGL module
- withhout using QGLWidget. When using QGLContext::currentContext(), it will ask
- QPlatformGLContext for the currentContext. Then a corresponding QGLContext will be returned,
- which maps to the QPlatformGLContext.
+ function. This is how QPlatformOpenGLContext also makes it possible to use the QtGui module
+ withhout using QOpenGLWidget. When using QOpenGLContext::currentContext(), it will ask
+ QPlatformOpenGLContext for the currentContext. Then a corresponding QOpenGLContext will be returned,
+ which maps to the QPlatformOpenGLContext.
*/
-/*! \fn void QPlatformGLContext::swapBuffers()
+/*! \fn void QPlatformOpenGLContext::swapBuffers()
Reimplement in subclass to native swap buffers calls
The implementation must support being called in a thread different than the gui-thread.
*/
-/*! \fn void *QPlatformGLContext::getProcAddress(const QString &procName)
+/*! \fn void *QPlatformOpenGLContext::getProcAddress(const QString &procName)
Reimplement in subclass to native getProcAddr calls.
Note: its convenient to use qPrintable(const QString &str) to get the const char * pointer
*/
-/*! \fn QPlatformWindowFormat QPlatformGLContext::platformWindowFormat() const
+/*! \fn QPlatformWindowFormat QPlatformOpenGLContext::platformWindowFormat() const
QWidget has the function qplatformWindowFormat(). That function is for the application
programmer to request the format of the window and the context that he wants.
Reimplement this function in a subclass to indicate what format the glContext actually has.
*/
-struct QPlatformGLContextPrivate
+struct QPlatformOpenGLContextPrivate
{
- QGuiGLContext *context;
+ QOpenGLContext *context;
};
-QPlatformGLContext::QPlatformGLContext()
- : d_ptr(new QPlatformGLContextPrivate)
+QPlatformOpenGLContext::QPlatformOpenGLContext()
+ : d_ptr(new QPlatformOpenGLContextPrivate)
{
- Q_D(QPlatformGLContext);
+ Q_D(QPlatformOpenGLContext);
d->context = 0;
}
-QPlatformGLContext::~QPlatformGLContext()
+QPlatformOpenGLContext::~QPlatformOpenGLContext()
{
}
-QGuiGLContext *QPlatformGLContext::context() const
+QOpenGLContext *QPlatformOpenGLContext::context() const
{
- Q_D(const QPlatformGLContext);
+ Q_D(const QPlatformOpenGLContext);
return d->context;
}
-void QPlatformGLContext::setContext(QGuiGLContext *context)
+void QPlatformOpenGLContext::setContext(QOpenGLContext *context)
{
- Q_D(QPlatformGLContext);
+ Q_D(QPlatformOpenGLContext);
d->context = context;
}
diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformopenglcontext_qpa.h
index 30d7186bd1..902ccdec6d 100644
--- a/src/gui/kernel/qplatformglcontext_qpa.h
+++ b/src/gui/kernel/qplatformopenglcontext_qpa.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -67,14 +67,14 @@ private:
friend class QPlatformWindow;
};
-class QPlatformGLContextPrivate;
+class QPlatformOpenGLContextPrivate;
-class Q_GUI_EXPORT QPlatformGLContext
+class Q_GUI_EXPORT QPlatformOpenGLContext
{
- Q_DECLARE_PRIVATE(QPlatformGLContext)
+ Q_DECLARE_PRIVATE(QPlatformOpenGLContext)
public:
- QPlatformGLContext();
- virtual ~QPlatformGLContext();
+ QPlatformOpenGLContext();
+ virtual ~QPlatformOpenGLContext();
virtual QSurfaceFormat format() const = 0;
@@ -85,16 +85,16 @@ public:
virtual void (*getProcAddress(const QByteArray &procName)) () = 0;
- QGuiGLContext *context() const;
+ QOpenGLContext *context() const;
private:
- friend class QGuiGLContext;
+ friend class QOpenGLContext;
- QScopedPointer<QPlatformGLContextPrivate> d_ptr;
+ QScopedPointer<QPlatformOpenGLContextPrivate> d_ptr;
- void setContext(QGuiGLContext *context);
+ void setContext(QOpenGLContext *context);
- Q_DISABLE_COPY(QPlatformGLContext)
+ Q_DISABLE_COPY(QPlatformOpenGLContext)
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h
index 8d3dd4cc71..3851b1821a 100644
--- a/src/gui/kernel/qplatformscreen_qpa.h
+++ b/src/gui/kernel/qplatformscreen_qpa.h
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
class QPlatformBackingStore;
-class QPlatformGLContext;
+class QPlatformOpenGLContext;
class QPlatformScreenPrivate;
class QPlatformWindow;
class QScreen;
diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp
index 766967eafa..0734fb7a26 100644
--- a/src/gui/kernel/qplatformwindow_qpa.cpp
+++ b/src/gui/kernel/qplatformwindow_qpa.cpp
@@ -260,7 +260,7 @@ bool QPlatformWindow::setMouseGrabEnabled(bool grab)
However, it is not concerned with how Qt renders into the window it represents.
Visible QWindows will always have a QPlatformWindow. However, it is not necessary for
- all windows to have a QWindowSurface. This is the case for QGLWidget. And could be the case for
+ all windows to have a QWindowSurface. This is the case for QOpenGLWidget. And could be the case for
windows where some 3.party renders into it.
The platform specific window handle can be retrieved by the winId function.
@@ -268,7 +268,7 @@ bool QPlatformWindow::setMouseGrabEnabled(bool grab)
QPlatformWindow is also the way QPA defines how native child windows should be supported
through the setParent function.
- The only way to retrieve a QPlatformGLContext in QPA is by calling the glContext() function
+ The only way to retrieve a QPlatformOpenGLContext in QPA is by calling the glContext() function
on QPlatformWindow.
\sa QWindowSurface, QWindow
diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h
index 680b24ac9b..ef2e07d774 100644
--- a/src/gui/kernel/qplatformwindow_qpa.h
+++ b/src/gui/kernel/qplatformwindow_qpa.h
@@ -47,7 +47,7 @@
#include <QtCore/qstring.h>
#include <QtGui/qwindowdefs.h>
#include <QtGui/qwindow.h>
-#include <QtGui/qplatformglcontext_qpa.h>
+#include <QtGui/qplatformopenglcontext_qpa.h>
QT_BEGIN_HEADER
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index 063e68d29f..c53c510d8c 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -44,6 +44,14 @@
#include <QtCore/qatomic.h>
#include <QtCore/QDebug>
+#ifdef major
+#undef major
+#endif
+
+#ifdef minor
+#undef minor
+#endif
+
class QSurfaceFormatPrivate
{
public:
@@ -59,6 +67,8 @@ public:
, swapBehavior(QSurfaceFormat::DefaultSwapBehavior)
, numSamples(-1)
, profile(QSurfaceFormat::NoProfile)
+ , major(1)
+ , minor(1)
{
}
@@ -73,7 +83,9 @@ public:
stencilSize(other->stencilSize),
swapBehavior(other->swapBehavior),
numSamples(other->numSamples),
- profile(other->profile)
+ profile(other->profile),
+ major(other->major),
+ minor(other->minor)
{
}
@@ -88,6 +100,8 @@ public:
QSurfaceFormat::SwapBehavior swapBehavior;
int numSamples;
QSurfaceFormat::OpenGLContextProfile profile;
+ int major;
+ int minor;
};
QSurfaceFormat::QSurfaceFormat() : d(new QSurfaceFormatPrivate)
@@ -351,6 +365,12 @@ void QSurfaceFormat::setAlphaBufferSize(int size)
}
}
+/*!
+ Sets the desired OpenGL context profile.
+
+ This setting is ignored if the requested OpenGL version is
+ less than 3.2.
+*/
void QSurfaceFormat::setProfile(OpenGLContextProfile profile)
{
if (d->profile != profile) {
@@ -364,6 +384,38 @@ QSurfaceFormat::OpenGLContextProfile QSurfaceFormat::profile() const
return d->profile;
}
+/*!
+ Sets the desired major OpenGL version.
+*/
+void QSurfaceFormat::setMajorVersion(int major)
+{
+ d->major = major;
+}
+
+/*!
+ Returns the major OpenGL version.
+*/
+int QSurfaceFormat::majorVersion() const
+{
+ return d->major;
+}
+
+/*!
+ Sets the desired minor OpenGL version.
+*/
+void QSurfaceFormat::setMinorVersion(int minor)
+{
+ d->minor = minor;
+}
+
+/*!
+ Returns the minor OpenGL version.
+*/
+int QSurfaceFormat::minorVersion() const
+{
+ return d->minor;
+}
+
bool operator==(const QSurfaceFormat& a, const QSurfaceFormat& b)
{
return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
index 6e89aa667b..f305edbcc9 100644
--- a/src/gui/kernel/qsurfaceformat.h
+++ b/src/gui/kernel/qsurfaceformat.h
@@ -49,14 +49,16 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-class QGuiGLContext;
+class QOpenGLContext;
class QSurfaceFormatPrivate;
class Q_GUI_EXPORT QSurfaceFormat
{
public:
enum FormatOption {
- StereoBuffers = 0x0001
+ StereoBuffers = 0x0001,
+ DebugContext = 0x0002,
+ DeprecatedFunctions = 0x0004
};
Q_DECLARE_FLAGS(FormatOptions, FormatOption)
@@ -105,6 +107,12 @@ public:
void setProfile(OpenGLContextProfile profile);
OpenGLContextProfile profile() const;
+ void setMajorVersion(int majorVersion);
+ int majorVersion() const;
+
+ void setMinorVersion(int minorVersion);
+ int minorVersion() const;
+
bool stereo() const;
void setStereo(bool enable);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 6fbc249631..c6e479358d 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -43,8 +43,8 @@
#include "qplatformwindow_qpa.h"
#include "qsurfaceformat.h"
-#include "qplatformglcontext_qpa.h"
-#include "qguiglcontext_qpa.h"
+#include "qplatformopenglcontext_qpa.h"
+#include "qopenglcontext.h"
#include "qscreen.h"
#include "qwindow_p.h"
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
new file mode 100644
index 0000000000..0401769ceb
--- /dev/null
+++ b/src/gui/opengl/opengl.pri
@@ -0,0 +1,44 @@
+# Qt gui library, opengl module
+
+contains(QT_CONFIG, opengl):CONFIG += opengl
+contains(QT_CONFIG, opengles2):CONFIG += opengles2
+contains(QT_CONFIG, egl):CONFIG += egl
+
+HEADERS += opengl/qopengl.h \
+ opengl/qopengl_p.h \
+ opengl/qopenglfunctions.h \
+ opengl/qopenglframebufferobject.h \
+ opengl/qopenglframebufferobject_p.h \
+ opengl/qopenglpaintdevice_p.h \
+ opengl/qopenglbuffer.h \
+ opengl/qopenglshaderprogram.h \
+ opengl/qopenglextensions_p.h \
+ opengl/qopenglgradientcache_p.h \
+ opengl/qopenglengineshadermanager_p.h \
+ opengl/qopengl2pexvertexarray_p.h \
+ opengl/qpaintengineex_opengl2_p.h \
+ opengl/qopenglengineshadersource_p.h \
+ opengl/qopenglcustomshaderstage_p.h \
+ opengl/qtriangulatingstroker_p.h \
+ opengl/qtriangulator_p.h \
+ opengl/qrbtree_p.h \
+ opengl/qtextureglyphcache_gl_p.h \
+ opengl/qopenglshadercache_p.h \
+ opengl/qopenglshadercache_meego_p.h
+
+SOURCES += opengl/qopengl.cpp \
+ opengl/qopenglfunctions.cpp \
+ opengl/qopenglframebufferobject.cpp \
+ opengl/qopenglpaintdevice.cpp \
+ opengl/qopenglbuffer.cpp \
+ opengl/qopenglshaderprogram.cpp \
+ opengl/qopenglgradientcache.cpp \
+ opengl/qopenglengineshadermanager.cpp \
+ opengl/qopengl2pexvertexarray.cpp \
+ opengl/qpaintengineex_opengl2.cpp \
+ opengl/qopenglcustomshaderstage.cpp \
+ opengl/qtriangulatingstroker.cpp \
+ opengl/qtriangulator.cpp \
+ opengl/qtextureglyphcache_gl.cpp
+
+#INCLUDEPATH += ../3rdparty/harfbuzz/src
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
new file mode 100644
index 0000000000..3233fcfa5b
--- /dev/null
+++ b/src/gui/opengl/qopengl.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengl_p.h"
+
+#include "qopenglcontext.h"
+
+QT_BEGIN_NAMESPACE
+
+QOpenGLExtensionMatcher::QOpenGLExtensionMatcher(const char *str)
+{
+ init(str);
+}
+
+typedef GLubyte * (*qt_glGetStringi)(GLenum, GLuint);
+
+#ifndef GL_NUM_EXTENSIONS
+#define GL_NUM_EXTENSIONS 0x821D
+#endif
+
+QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()
+{
+ const char *extensionStr = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
+
+ if (extensionStr) {
+ init(extensionStr);
+ } else {
+ // clear error state
+ while (glGetError()) {}
+
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx) {
+ qt_glGetStringi glGetStringi = (qt_glGetStringi)ctx->getProcAddress("glGetStringi");
+
+ if (!glGetStringi)
+ return;
+
+ GLint numExtensions;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions);
+
+ for (int i = 0; i < numExtensions; ++i) {
+ const char *str = reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i));
+
+ m_offsets << m_extensions.size();
+
+ while (*str != 0)
+ m_extensions.append(*str++);
+ m_extensions.append(' ');
+ }
+ }
+ }
+}
+
+void QOpenGLExtensionMatcher::init(const char *str)
+{
+ m_extensions = str;
+
+ // make sure extension string ends with a space
+ if (!m_extensions.endsWith(' '))
+ m_extensions.append(' ');
+
+ int index = 0;
+ int next = 0;
+ while ((next = m_extensions.indexOf(' ', index)) >= 0) {
+ m_offsets << index;
+ index = next + 1;
+ }
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
new file mode 100644
index 0000000000..7d75794956
--- /dev/null
+++ b/src/gui/opengl/qopengl.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGL_H
+#define QOPENGL_H
+
+#include <qglobal.h>
+
+QT_BEGIN_HEADER
+
+#if 1
+#if defined(QT_OPENGL_ES_2)
+# if defined(Q_OS_MAC)
+# include <OpenGLES/ES2/gl.h>
+# else
+# include <GLES2/gl2.h>
+# endif
+# ifndef GL_DOUBLE
+# define GL_DOUBLE GL_FLOAT
+# endif
+# ifndef GLdouble
+typedef GLfloat GLdouble;
+# endif
+#else
+# if defined(Q_OS_MAC)
+# include <OpenGL/gl.h>
+# else
+# include <GL/gl.h>
+# endif
+#endif
+#endif
+
+QT_END_HEADER
+
+#endif // QOPENGL_H
diff --git a/src/gui/opengl/qopengl2pexvertexarray.cpp b/src/gui/opengl/qopengl2pexvertexarray.cpp
new file mode 100644
index 0000000000..ec26fdbf5b
--- /dev/null
+++ b/src/gui/opengl/qopengl2pexvertexarray.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopengl2pexvertexarray_p.h"
+
+#include <private/qbezier_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QOpenGL2PEXVertexArray::clear()
+{
+ vertexArray.reset();
+ vertexArrayStops.reset();
+ boundingRectDirty = true;
+}
+
+
+QOpenGLRect QOpenGL2PEXVertexArray::boundingRect() const
+{
+ if (boundingRectDirty)
+ return QOpenGLRect(0.0, 0.0, 0.0, 0.0);
+ else
+ return QOpenGLRect(minX, minY, maxX, maxY);
+}
+
+void QOpenGL2PEXVertexArray::addClosingLine(int index)
+{
+ QPointF point(vertexArray.at(index));
+ if (point != QPointF(vertexArray.last()))
+ vertexArray.add(point);
+}
+
+void QOpenGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
+{
+ const QPointF *const points = reinterpret_cast<const QPointF *>(path.points());
+ const QPainterPath::ElementType *const elements = path.elements();
+
+ QPointF sum = points[subPathIndex];
+ int count = 1;
+
+ for (int i = subPathIndex + 1; i < path.elementCount() && (!elements || elements[i] != QPainterPath::MoveToElement); ++i) {
+ sum += points[i];
+ ++count;
+ }
+
+ const QPointF centroid = sum / qreal(count);
+ vertexArray.add(centroid);
+}
+
+void QOpenGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline)
+{
+ const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
+ const QPainterPath::ElementType* const elements = path.elements();
+
+ if (boundingRectDirty) {
+ minX = maxX = points[0].x();
+ minY = maxY = points[0].y();
+ boundingRectDirty = false;
+ }
+
+ if (!outline && !path.isConvex())
+ addCentroid(path, 0);
+
+ int lastMoveTo = vertexArray.size();
+ vertexArray.add(points[0]); // The first element is always a moveTo
+
+ do {
+ if (!elements) {
+// qDebug("QVectorPath has no elements");
+ // If the path has a null elements pointer, the elements implicitly
+ // start with a moveTo (already added) and continue with lineTos:
+ for (int i=1; i<path.elementCount(); ++i)
+ lineToArray(points[i].x(), points[i].y());
+
+ break;
+ }
+// qDebug("QVectorPath has element types");
+
+ for (int i=1; i<path.elementCount(); ++i) {
+ switch (elements[i]) {
+ case QPainterPath::MoveToElement:
+ if (!outline)
+ addClosingLine(lastMoveTo);
+// qDebug("element[%d] is a MoveToElement", i);
+ vertexArrayStops.add(vertexArray.size());
+ if (!outline) {
+ if (!path.isConvex()) addCentroid(path, i);
+ lastMoveTo = vertexArray.size();
+ }
+ lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex
+ break;
+ case QPainterPath::LineToElement:
+// qDebug("element[%d] is a LineToElement", i);
+ lineToArray(points[i].x(), points[i].y());
+ break;
+ case QPainterPath::CurveToElement: {
+ QBezier b = QBezier::fromPoints(*(((const QPointF *) points) + i - 1),
+ points[i],
+ points[i+1],
+ points[i+2]);
+ QRectF bounds = b.bounds();
+ // threshold based on same algorithm as in qtriangulatingstroker.cpp
+ int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6));
+ if (threshold < 3) threshold = 3;
+ qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1);
+ for (int t=0; t<threshold; ++t) {
+ QPointF pt = b.pointAt(t * one_over_threshold_minus_1);
+ lineToArray(pt.x(), pt.y());
+ }
+ i += 2;
+ break; }
+ default:
+ break;
+ }
+ }
+ } while (0);
+
+ if (!outline)
+ addClosingLine(lastMoveTo);
+ vertexArrayStops.add(vertexArray.size());
+}
+
+void QOpenGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y)
+{
+ vertexArray.add(QOpenGLPoint(x, y));
+
+ if (x > maxX)
+ maxX = x;
+ else if (x < minX)
+ minX = x;
+ if (y > maxY)
+ maxY = y;
+ else if (y < minY)
+ minY = y;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengl2pexvertexarray_p.h b/src/gui/opengl/qopengl2pexvertexarray_p.h
new file mode 100644
index 0000000000..5ad4f7a237
--- /dev/null
+++ b/src/gui/opengl/qopengl2pexvertexarray_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QOPENGL2PEXVERTEXARRAY_P_H
+#define QOPENGL2PEXVERTEXARRAY_P_H
+
+#include <QRectF>
+
+#include <private/qdatabuffer_p.h>
+#include <private/qvectorpath_p.h>
+#include <private/qopenglcontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLPoint
+{
+public:
+ QOpenGLPoint(GLfloat new_x, GLfloat new_y) :
+ x(new_x), y(new_y) {};
+
+ QOpenGLPoint(const QPointF &p) :
+ x(p.x()), y(p.y()) {};
+
+ QOpenGLPoint(const QPointF* p) :
+ x(p->x()), y(p->y()) {};
+
+ GLfloat x;
+ GLfloat y;
+
+ operator QPointF() {return QPointF(x,y);}
+ operator QPointF() const {return QPointF(x,y);}
+};
+
+struct QOpenGLRect
+{
+ QOpenGLRect(const QRectF &r)
+ : left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
+
+ QOpenGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
+ : left(l), top(t), right(r), bottom(b) {}
+
+ GLfloat left;
+ GLfloat top;
+ GLfloat right;
+ GLfloat bottom;
+
+ operator QRectF() const {return QRectF(left, top, right-left, bottom-top);}
+};
+
+class QOpenGL2PEXVertexArray
+{
+public:
+ QOpenGL2PEXVertexArray() :
+ vertexArray(0), vertexArrayStops(0),
+ maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
+ boundingRectDirty(true)
+ { }
+
+ inline void addRect(const QRectF &rect)
+ {
+ qreal top = rect.top();
+ qreal left = rect.left();
+ qreal bottom = rect.bottom();
+ qreal right = rect.right();
+
+ vertexArray << QOpenGLPoint(left, top)
+ << QOpenGLPoint(right, top)
+ << QOpenGLPoint(right, bottom)
+ << QOpenGLPoint(right, bottom)
+ << QOpenGLPoint(left, bottom)
+ << QOpenGLPoint(left, top);
+ }
+
+ inline void addQuad(const QRectF &rect)
+ {
+ qreal top = rect.top();
+ qreal left = rect.left();
+ qreal bottom = rect.bottom();
+ qreal right = rect.right();
+
+ vertexArray << QOpenGLPoint(left, top)
+ << QOpenGLPoint(right, top)
+ << QOpenGLPoint(left, bottom)
+ << QOpenGLPoint(right, bottom);
+
+ }
+
+ inline void addVertex(const GLfloat x, const GLfloat y)
+ {
+ vertexArray.add(QOpenGLPoint(x, y));
+ }
+
+ void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
+ void clear();
+
+ QOpenGLPoint* data() {return vertexArray.data();}
+ int *stops() const { return vertexArrayStops.data(); }
+ int stopCount() const { return vertexArrayStops.size(); }
+ QOpenGLRect boundingRect() const;
+
+ int vertexCount() const { return vertexArray.size(); }
+
+ void lineToArray(const GLfloat x, const GLfloat y);
+
+private:
+ QDataBuffer<QOpenGLPoint> vertexArray;
+ QDataBuffer<int> vertexArrayStops;
+
+ GLfloat maxX;
+ GLfloat maxY;
+ GLfloat minX;
+ GLfloat minY;
+ bool boundingRectDirty;
+ void addClosingLine(int index);
+ void addCentroid(const QVectorPath &path, int subPathIndex);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h
new file mode 100644
index 0000000000..309ea22acd
--- /dev/null
+++ b/src/gui/opengl/qopengl_p.h
@@ -0,0 +1,200 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGL_P_H
+#define QOPENGL_P_H
+
+#include <qopengl.h>
+#include <private/qopenglcontext_p.h>
+
+#include <qthreadstorage.h>
+#include <qcache.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLExtensionMatcher
+{
+public:
+ QOpenGLExtensionMatcher(const char *str);
+ QOpenGLExtensionMatcher();
+
+ bool match(const char *str) const {
+ int str_length = qstrlen(str);
+
+ Q_ASSERT(str);
+ Q_ASSERT(str_length > 0);
+ Q_ASSERT(str[str_length-1] != ' ');
+
+ for (int i = 0; i < m_offsets.size(); ++i) {
+ const char *extension = m_extensions.constData() + m_offsets.at(i);
+ if (qstrncmp(extension, str, str_length) == 0 && extension[str_length] == ' ')
+ return true;
+ }
+ return false;
+ }
+
+private:
+ void init(const char *str);
+
+ QByteArray m_extensions;
+ QVector<int> m_offsets;
+};
+
+// this is a class that wraps a QThreadStorage object for storing
+// thread local instances of the GL 1 and GL 2 paint engines
+
+class QPaintEngine;
+
+template <class T>
+class QOpenGLEngineThreadStorage
+{
+public:
+ QPaintEngine *engine() {
+ QPaintEngine *&localEngine = storage.localData();
+ if (!localEngine)
+ localEngine = new T;
+ return localEngine;
+ }
+
+private:
+ QThreadStorage<QPaintEngine *> storage;
+};
+
+class QOpenGLTexture : public QOpenGLSharedResource {
+public:
+ QOpenGLTexture(QOpenGLContext *ctx, GLuint id, bool inverted)
+ : QOpenGLSharedResource(ctx->shareGroup())
+ , m_id(id)
+ , m_inverted(inverted)
+ {
+ }
+
+ GLuint id() const { return m_id; }
+ bool invertedY() const { return m_inverted; }
+
+protected:
+ void invalidateResource()
+ {
+ m_id = 0;
+ }
+
+ void freeResource(QOpenGLContext *)
+ {
+ glDeleteTextures(1, &m_id);
+ }
+
+private:
+ GLuint m_id;
+ bool m_inverted;
+};
+
+struct QOpenGLTextureCacheKey {
+ qint64 key;
+ QOpenGLContextGroup *group;
+};
+
+inline bool operator==(const QOpenGLTextureCacheKey &a, const QOpenGLTextureCacheKey &b)
+{
+ return a.key == b.key && a.group == b.group;
+}
+
+inline uint qHash(const QOpenGLTextureCacheKey &key)
+{
+ return qHash(key.key) ^ qHash(key.group);
+}
+
+class QPlatformPixmap;
+
+class QOpenGLTextureCache {
+public:
+ QOpenGLTextureCache();
+ ~QOpenGLTextureCache();
+
+ void insert(QOpenGLContext *ctx, qint64 key, QOpenGLTexture *texture, int cost);
+ void remove(qint64 key);
+ inline int size();
+ inline void setMaxCost(int newMax);
+ inline int maxCost();
+ inline QOpenGLTexture* getTexture(QOpenGLContext *ctx, qint64 key);
+
+ bool remove(QOpenGLContext *ctx, GLuint textureId);
+ void removeContextTextures(QOpenGLContext *ctx);
+ static QOpenGLTextureCache *instance();
+ static void cleanupTexturesForCacheKey(qint64 cacheKey);
+ static void cleanupTexturesForPixampData(QPlatformPixmap* pixmap);
+ static void cleanupBeforePixmapDestruction(QPlatformPixmap* pixmap);
+
+private:
+ QCache<QOpenGLTextureCacheKey, QOpenGLTexture> m_cache;
+ QReadWriteLock m_lock;
+};
+
+int QOpenGLTextureCache::size() {
+ QReadLocker locker(&m_lock);
+ return m_cache.size();
+}
+
+void QOpenGLTextureCache::setMaxCost(int newMax)
+{
+ QWriteLocker locker(&m_lock);
+ m_cache.setMaxCost(newMax);
+}
+
+int QOpenGLTextureCache::maxCost()
+{
+ QReadLocker locker(&m_lock);
+ return m_cache.maxCost();
+}
+
+QOpenGLTexture* QOpenGLTextureCache::getTexture(QOpenGLContext *ctx, qint64 key)
+{
+ QReadLocker locker(&m_lock);
+ const QOpenGLTextureCacheKey cacheKey = { key, ctx->shareGroup() };
+ return m_cache.object(cacheKey);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOPENGL_H
diff --git a/src/gui/opengl/qopenglbuffer.cpp b/src/gui/opengl/qopenglbuffer.cpp
new file mode 100644
index 0000000000..612938df16
--- /dev/null
+++ b/src/gui/opengl/qopenglbuffer.cpp
@@ -0,0 +1,582 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qopengl.h>
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtCore/qatomic.h>
+#include "qopenglbuffer.h"
+#include <private/qopenglextensions_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLBuffer
+ \brief The QOpenGLBuffer class provides functions for creating and managing GL buffer objects.
+ \since 4.7
+ \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.
+
+ QOpenGLBuffer objects can be copied around as a reference to the
+ underlying GL buffer object:
+
+ \code
+ QOpenGLBuffer buffer1(QOpenGLBuffer::IndexBuffer);
+ buffer1.create();
+
+ QOpenGLBuffer buffer2 = buffer1;
+ \endcode
+
+ QOpenGLBuffer 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.
+*/
+
+/*!
+ \enum QOpenGLBuffer::Type
+ This enum defines the type of GL buffer object to create with QOpenGLBuffer.
+
+ \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 QOpenGLBuffer::UsagePattern
+ This enum defines the usage pattern of a QOpenGLBuffer 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 QOpenGLBuffer::Access
+ This enum defines the access mode for QOpenGLBuffer::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 QOpenGLBufferPrivate
+{
+public:
+ QOpenGLBufferPrivate(QOpenGLBuffer::Type t)
+ : ref(1),
+ type(t),
+ guard(0),
+ usagePattern(QOpenGLBuffer::StaticDraw),
+ actualUsagePattern(QOpenGLBuffer::StaticDraw),
+ funcs(0)
+ {
+ }
+
+ QAtomicInt ref;
+ QOpenGLBuffer::Type type;
+ QOpenGLSharedResourceGuard *guard;
+ QOpenGLBuffer::UsagePattern usagePattern;
+ QOpenGLBuffer::UsagePattern actualUsagePattern;
+ QOpenGLExtensions *funcs;
+};
+
+/*!
+ Constructs a new buffer object of type QOpenGLBuffer::VertexBuffer.
+
+ Note: this constructor just creates the QOpenGLBuffer instance. The actual
+ buffer object in the GL server is not created until create() is called.
+
+ \sa create()
+*/
+QOpenGLBuffer::QOpenGLBuffer()
+ : d_ptr(new QOpenGLBufferPrivate(QOpenGLBuffer::VertexBuffer))
+{
+}
+
+/*!
+ Constructs a new buffer object of \a type.
+
+ Note: this constructor just creates the QOpenGLBuffer instance. The actual
+ buffer object in the GL server is not created until create() is called.
+
+ \sa create()
+*/
+QOpenGLBuffer::QOpenGLBuffer(QOpenGLBuffer::Type type)
+ : d_ptr(new QOpenGLBufferPrivate(type))
+{
+}
+
+/*!
+ Constructs a shallow copy of \a other.
+
+ Note: QOpenGLBuffer does not implement copy-on-write semantics,
+ so \a other will be affected whenever the copy is modified.
+*/
+QOpenGLBuffer::QOpenGLBuffer(const QOpenGLBuffer &other)
+ : d_ptr(other.d_ptr)
+{
+ d_ptr->ref.ref();
+}
+
+#define ctx QOpenGLContext::currentContext();
+
+/*!
+ Destroys this buffer object, including the storage being
+ used in the GL server.
+*/
+QOpenGLBuffer::~QOpenGLBuffer()
+{
+ if (!d_ptr->ref.deref()) {
+ destroy();
+ delete d_ptr;
+ }
+}
+
+/*!
+ Assigns a shallow copy of \a other to this object.
+
+ Note: QOpenGLBuffer does not implement copy-on-write semantics,
+ so \a other will be affected whenever the copy is modified.
+*/
+QOpenGLBuffer &QOpenGLBuffer::operator=(const QOpenGLBuffer &other)
+{
+ if (d_ptr != other.d_ptr) {
+ other.d_ptr->ref.ref();
+ if (!d_ptr->ref.deref())
+ destroy();
+ d_ptr = other.d_ptr;
+ }
+ return *this;
+}
+
+/*!
+ Returns the type of buffer represented by this object.
+*/
+QOpenGLBuffer::Type QOpenGLBuffer::type() const
+{
+ Q_D(const QOpenGLBuffer);
+ return d->type;
+}
+
+/*!
+ Returns the usage pattern for this buffer object.
+ The default value is StaticDraw.
+
+ \sa setUsagePattern()
+*/
+QOpenGLBuffer::UsagePattern QOpenGLBuffer::usagePattern() const
+{
+ Q_D(const QOpenGLBuffer);
+ 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 QOpenGLBuffer::setUsagePattern(QOpenGLBuffer::UsagePattern value)
+{
+ Q_D(QOpenGLBuffer);
+ d->usagePattern = d->actualUsagePattern = value;
+}
+
+#undef ctx
+
+namespace {
+ void freeBufferFunc(QOpenGLFunctions *funcs, GLuint id)
+ {
+ funcs->glDeleteBuffers(1, &id);
+ }
+}
+
+/*!
+ Creates the buffer object in the GL server. Returns true if
+ the object was created; false otherwise.
+
+ This function must be called with a current QOpenGLContext.
+ 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 QOpenGLContext.
+
+ \sa isCreated(), allocate(), write(), destroy()
+*/
+bool QOpenGLBuffer::create()
+{
+ Q_D(QOpenGLBuffer);
+ if (d->guard && d->guard->id())
+ return true;
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx) {
+ delete d->funcs;
+ d->funcs = new QOpenGLExtensions(ctx);
+ GLuint bufferId = 0;
+ d->funcs->glGenBuffers(1, &bufferId);
+ if (bufferId) {
+ if (d->guard)
+ d->guard->free();
+
+ d->guard = new QOpenGLSharedResourceGuard(ctx, bufferId, freeBufferFunc);
+ return true;
+ }
+ }
+ return false;
+}
+
+#define ctx QOpenGLContext::currentContext()
+
+/*!
+ Returns true if this buffer has been created; false otherwise.
+
+ \sa create(), destroy()
+*/
+bool QOpenGLBuffer::isCreated() const
+{
+ Q_D(const QOpenGLBuffer);
+ 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 QOpenGLBuffer::destroy()
+{
+ Q_D(QOpenGLBuffer);
+ 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 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 QOpenGLBuffer::read(int offset, void *data, int count)
+{
+#if !defined(QT_OPENGL_ES)
+ Q_D(QOpenGLBuffer);
+ if (!d->funcs->hasOpenGLFeature(QOpenGLFunctions::Buffers) || !d->guard->id())
+ return false;
+ while (glGetError() != GL_NO_ERROR) ; // Clear error state.
+ d->funcs->glGetBufferSubData(d->type, offset, count, data);
+ return 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 QOpenGLBuffer::write(int offset, const void *data, int count)
+{
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::allocate(): buffer not created");
+#endif
+ Q_D(QOpenGLBuffer);
+ 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 QOpenGLBuffer::allocate(const void *data, int count)
+{
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::allocate(): buffer not created");
+#endif
+ Q_D(QOpenGLBuffer);
+ if (d->guard && d->guard->id())
+ d->funcs->glBufferData(d->type, count, data, d->actualUsagePattern);
+}
+
+/*!
+ \fn void QOpenGLBuffer::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 false if binding was not possible, usually because
+ type() is not supported on this GL implementation.
+
+ The buffer must be bound to the same QOpenGLContext current when create()
+ was called, or to another QOpenGLContext that is sharing with it.
+ Otherwise, false will be returned from this function.
+
+ \sa release(), create()
+*/
+bool QOpenGLBuffer::bind()
+{
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::bind(): buffer not created");
+#endif
+ Q_D(const QOpenGLBuffer);
+ GLuint bufferId = d->guard ? d->guard->id() : 0;
+ if (bufferId) {
+ if (d->guard->group() != QOpenGLContextGroup::currentContextGroup()) {
+#ifndef QT_NO_DEBUG
+ qWarning("QOpenGLBuffer::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 QOpenGLContext current
+ as when bind() was called on the buffer.
+
+ \sa bind()
+*/
+void QOpenGLBuffer::release()
+{
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::release(): buffer not created");
+#endif
+ Q_D(const QOpenGLBuffer);
+ if (d->guard && d->guard->id())
+ d->funcs->glBindBuffer(d->type, 0);
+}
+
+#undef ctx
+
+/*!
+ Releases the buffer associated with \a type in the current
+ QOpenGLContext.
+
+ This function is a direct call to \c{glBindBuffer(type, 0)}
+ for use when the caller does not know which QOpenGLBuffer has
+ been bound to the context but wants to make sure that it
+ is released.
+
+ \code
+ QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
+ \endcode
+*/
+void QOpenGLBuffer::release(QOpenGLBuffer::Type type)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (ctx) {
+ QOpenGLFunctions(ctx).glBindBuffer(GLenum(type), 0);
+ }
+}
+
+#define ctx QOpenGLContext::currentContext()
+
+/*!
+ Returns the GL identifier associated with this buffer; zero if
+ the buffer has not been created.
+
+ \sa isCreated()
+*/
+GLuint QOpenGLBuffer::bufferId() const
+{
+ Q_D(const QOpenGLBuffer);
+ 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 QOpenGLBuffer::size() const
+{
+ Q_D(const QOpenGLBuffer);
+ 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 *QOpenGLBuffer::map(QOpenGLBuffer::Access access)
+{
+ Q_D(QOpenGLBuffer);
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::map(): buffer not created");
+#endif
+ if (!d->guard || !d->guard->id())
+ return 0;
+#if 0
+ if (!glMapBufferARB)
+ return 0;
+ return glMapBufferARB(d->type, access);
+#endif
+ Q_UNUSED(access);
+ qWarning("QOpenGLBuffer::map(): pending implementation");
+ return 0;
+}
+
+/*!
+ Unmaps the buffer after it was mapped into the application's
+ memory space with a previous call to map(). Returns 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 QOpenGLBuffer::unmap()
+{
+ Q_D(QOpenGLBuffer);
+#ifndef QT_NO_DEBUG
+ if (!isCreated())
+ qWarning("QOpenGLBuffer::unmap(): buffer not created");
+#endif
+ if (!d->guard || !d->guard->id())
+ return false;
+#if 0
+ if (!glUnmapBufferARB)
+ return false;
+ return glUnmapBufferARB(d->type) == GL_TRUE;
+#endif
+ qWarning("QOpenGLBuffer::map(): pending implementation");
+ return 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglbuffer.h b/src/gui/opengl/qopenglbuffer.h
new file mode 100644
index 0000000000..52a2c4d640
--- /dev/null
+++ b/src/gui/opengl/qopenglbuffer.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLBUFFER_H
+#define QOPENGLBUFFER_H
+
+#include <QtCore/qscopedpointer.h>
+#include <QtGui/qopengl.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QOpenGLBufferPrivate;
+
+class Q_GUI_EXPORT QOpenGLBuffer
+{
+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
+ };
+
+ QOpenGLBuffer();
+ explicit QOpenGLBuffer(QOpenGLBuffer::Type type);
+ QOpenGLBuffer(const QOpenGLBuffer &other);
+ ~QOpenGLBuffer();
+
+ QOpenGLBuffer &operator=(const QOpenGLBuffer &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
+ };
+
+ QOpenGLBuffer::Type type() const;
+
+ QOpenGLBuffer::UsagePattern usagePattern() const;
+ void setUsagePattern(QOpenGLBuffer::UsagePattern value);
+
+ bool create();
+ bool isCreated() const;
+
+ void destroy();
+
+ bool bind();
+ void release();
+
+ static void release(QOpenGLBuffer::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(0, count); }
+
+ void *map(QOpenGLBuffer::Access access);
+ bool unmap();
+
+private:
+ QOpenGLBufferPrivate *d_ptr;
+
+ Q_DECLARE_PRIVATE(QOpenGLBuffer)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/opengl/qopenglcolormap.cpp b/src/gui/opengl/qopenglcolormap.cpp
new file mode 100644
index 0000000000..386358ac23
--- /dev/null
+++ b/src/gui/opengl/qopenglcolormap.cpp
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QOpenGLColormap
+ \brief The QOpenGLColormap class is used for installing custom colormaps into
+ a QOpenGLWidget.
+
+ \module OpenGL
+ \ingroup painting-3D
+ \ingroup shared
+
+ QOpenGLColormap provides a platform independent way of specifying and
+ installing indexed colormaps for a QOpenGLWidget. QOpenGLColormap 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 doc/src/snippets/code/src_opengl_qopenglcolormap.cpp 0
+
+ \sa QOpenGLWidget::setColormap(), QOpenGLWidget::colormap()
+*/
+
+/*!
+ \fn Qt::HANDLE QOpenGLColormap::handle()
+
+ \internal
+
+ Returns the handle for this color map.
+*/
+
+/*!
+ \fn void QOpenGLColormap::setHandle(Qt::HANDLE handle)
+
+ \internal
+
+ Sets the handle for this color map to \a handle.
+*/
+
+#include "qopenglcolormap.h"
+
+QT_BEGIN_NAMESPACE
+
+QOpenGLColormap::QOpenGLColormapData QOpenGLColormap::shared_null = { Q_BASIC_ATOMIC_INITIALIZER(1), 0, 0 };
+
+/*!
+ Construct a QOpenGLColormap.
+*/
+QOpenGLColormap::QOpenGLColormap()
+ : d(&shared_null)
+{
+ d->ref.ref();
+}
+
+
+/*!
+ Construct a shallow copy of \a map.
+*/
+QOpenGLColormap::QOpenGLColormap(const QOpenGLColormap &map)
+ : d(map.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ Dereferences the QOpenGLColormap and deletes it if this was the last
+ reference to it.
+*/
+QOpenGLColormap::~QOpenGLColormap()
+{
+ if (!d->ref.deref())
+ cleanup(d);
+}
+
+void QOpenGLColormap::cleanup(QOpenGLColormap::QOpenGLColormapData *x)
+{
+ delete x->cells;
+ x->cells = 0;
+ delete x;
+}
+
+/*!
+ Assign a shallow copy of \a map to this QOpenGLColormap.
+*/
+QOpenGLColormap & QOpenGLColormap::operator=(const QOpenGLColormap &map)
+{
+ map.d->ref.ref();
+ if (!d->ref.deref())
+ cleanup(d);
+ d = map.d;
+ return *this;
+}
+
+/*!
+ \fn void QOpenGLColormap::detach()
+ \internal
+
+ Detaches this QOpenGLColormap from the shared block.
+*/
+
+void QOpenGLColormap::detach_helper()
+{
+ QOpenGLColormapData *x = new QOpenGLColormapData;
+ x->ref = 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 QOpenGLColormap::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 QOpenGLColormap::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(), "QOpenGLColormap::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 QOpenGLColormap::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 QOpenGLColormap::setEntry(int idx, const QColor &color)
+{
+ setEntry(idx, color.rgb());
+}
+
+/*!
+ Returns the QRgb value in the colorcell with index \a idx.
+*/
+QColor QOpenGLColormap::entryColor(int idx) const
+{
+ if (d == &shared_null || !d->cells)
+ return QColor();
+ else
+ return QColor(d->cells->at(idx));
+}
+
+/*!
+ Returns true if the colormap is empty or it is not in use
+ by a QOpenGLWidget; otherwise returns 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 QOpenGLWidget is also considered empty.
+
+ Compare size() with zero to determine if the colormap is empty
+ regardless of whether it is in use by a QOpenGLWidget or not.
+
+ \sa size()
+*/
+bool QOpenGLColormap::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 QOpenGLColormap::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 QOpenGLColormap::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 QOpenGLColormap::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/gui/opengl/qopenglcolormap.h b/src/gui/opengl/qopenglcolormap.h
new file mode 100644
index 0000000000..b05e3f331d
--- /dev/null
+++ b/src/gui/opengl/qopenglcolormap.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLCOLORMAP_H
+#define QOPENGLCOLORMAP_H
+
+#include <QtGui/qcolor.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class Q_GUI_EXPORT QOpenGLColormap
+{
+public:
+ QOpenGLColormap();
+ QOpenGLColormap(const QOpenGLColormap &);
+ ~QOpenGLColormap();
+
+ QOpenGLColormap &operator=(const QOpenGLColormap &);
+
+ bool isEmpty() const;
+ int size() const;
+ void detach();
+
+ 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;
+
+protected:
+ Qt::HANDLE handle() { return d ? d->cmapHandle : 0; }
+ void setHandle(Qt::HANDLE ahandle) { d->cmapHandle = ahandle; }
+
+private:
+ struct QOpenGLColormapData {
+ QBasicAtomicInt ref;
+ QVector<QRgb> *cells;
+ Qt::HANDLE cmapHandle;
+ };
+
+ QOpenGLColormapData *d;
+ static struct QOpenGLColormapData shared_null;
+ static void cleanup(QOpenGLColormapData *x);
+ void detach_helper();
+
+ friend class QOpenGLWidget;
+ friend class QOpenGLWidgetPrivate;
+};
+
+inline void QOpenGLColormap::detach()
+{
+ if (d->ref != 1)
+ detach_helper();
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOPENGLCOLORMAP_H
diff --git a/src/gui/opengl/qopenglcustomshaderstage.cpp b/src/gui/opengl/qopenglcustomshaderstage.cpp
new file mode 100644
index 0000000000..cbbf318249
--- /dev/null
+++ b/src/gui/opengl/qopenglcustomshaderstage.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglcustomshaderstage_p.h"
+#include "qopenglengineshadermanager_p.h"
+#include "qpaintengineex_opengl2_p.h"
+#include <private/qpainter_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLCustomShaderStagePrivate
+{
+public:
+ QOpenGLCustomShaderStagePrivate() :
+ m_manager(0) {}
+
+ QPointer<QOpenGLEngineShaderManager> m_manager;
+ QByteArray m_source;
+};
+
+
+
+
+QOpenGLCustomShaderStage::QOpenGLCustomShaderStage()
+ : d_ptr(new QOpenGLCustomShaderStagePrivate)
+{
+}
+
+QOpenGLCustomShaderStage::~QOpenGLCustomShaderStage()
+{
+ Q_D(QOpenGLCustomShaderStage);
+ if (d->m_manager) {
+ d->m_manager->removeCustomStage();
+ d->m_manager->sharedShaders->cleanupCustomStage(this);
+ }
+}
+
+void QOpenGLCustomShaderStage::setUniformsDirty()
+{
+ Q_D(QOpenGLCustomShaderStage);
+ if (d->m_manager)
+ d->m_manager->setDirty(); // ### Probably a bit overkill!
+}
+
+bool QOpenGLCustomShaderStage::setOnPainter(QPainter* p)
+{
+ Q_D(QOpenGLCustomShaderStage);
+ if (p->paintEngine()->type() != QPaintEngine::OpenGL2) {
+ qWarning("QOpenGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2");
+ return false;
+ }
+ if (d->m_manager)
+ qWarning("Custom shader is already set on a painter");
+
+ QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine());
+ d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
+ Q_ASSERT(d->m_manager);
+
+ d->m_manager->setCustomStage(this);
+ return true;
+}
+
+void QOpenGLCustomShaderStage::removeFromPainter(QPainter* p)
+{
+ Q_D(QOpenGLCustomShaderStage);
+ if (p->paintEngine()->type() != QPaintEngine::OpenGL2)
+ return;
+
+ QOpenGL2PaintEngineEx *engine = static_cast<QOpenGL2PaintEngineEx*>(p->paintEngine());
+ d->m_manager = QOpenGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
+ Q_ASSERT(d->m_manager);
+
+ // Just set the stage to null, don't call removeCustomStage().
+ // This should leave the program in a compiled/linked state
+ // if the next custom shader stage is this one again.
+ d->m_manager->setCustomStage(0);
+ d->m_manager = 0;
+}
+
+QByteArray QOpenGLCustomShaderStage::source() const
+{
+ Q_D(const QOpenGLCustomShaderStage);
+ return d->m_source;
+}
+
+// Called by the shader manager if another custom shader is attached or
+// the manager is deleted
+void QOpenGLCustomShaderStage::setInactive()
+{
+ Q_D(QOpenGLCustomShaderStage);
+ d->m_manager = 0;
+}
+
+void QOpenGLCustomShaderStage::setSource(const QByteArray& s)
+{
+ Q_D(QOpenGLCustomShaderStage);
+ d->m_source = s;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglcustomshaderstage_p.h b/src/gui/opengl/qopenglcustomshaderstage_p.h
new file mode 100644
index 0000000000..36ad307848
--- /dev/null
+++ b/src/gui/opengl/qopenglcustomshaderstage_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGL_CUSTOM_SHADER_STAGE_H
+#define QOPENGL_CUSTOM_SHADER_STAGE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QOpenGLShaderProgram>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QOpenGLCustomShaderStagePrivate;
+class Q_GUI_EXPORT QOpenGLCustomShaderStage
+{
+ Q_DECLARE_PRIVATE(QOpenGLCustomShaderStage)
+public:
+ QOpenGLCustomShaderStage();
+ virtual ~QOpenGLCustomShaderStage();
+ virtual void setUniforms(QOpenGLShaderProgram*) {}
+
+ void setUniformsDirty();
+
+ bool setOnPainter(QPainter*);
+ void removeFromPainter(QPainter*);
+ QByteArray source() const;
+
+ void setInactive();
+protected:
+ void setSource(const QByteArray&);
+
+private:
+ QOpenGLCustomShaderStagePrivate* d_ptr;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+
+#endif
diff --git a/src/gui/opengl/qopenglengineshadermanager.cpp b/src/gui/opengl/qopenglengineshadermanager.cpp
new file mode 100644
index 0000000000..91262dc1ce
--- /dev/null
+++ b/src/gui/opengl/qopenglengineshadermanager.cpp
@@ -0,0 +1,881 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglengineshadermanager_p.h"
+#include "qopenglengineshadersource_p.h"
+#include "qpaintengineex_opengl2_p.h"
+#include "qopenglshadercache_p.h"
+
+#include <QtGui/private/qopenglcontext_p.h>
+#include <QtCore/qthreadstorage.h>
+
+#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()
+ {
+ delete m_shaders;
+ m_shaders = 0;
+ }
+
+ void freeResource(QOpenGLContext *)
+ {
+ }
+
+ 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() : 0;
+ }
+
+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(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] = 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_CMO] = qopenglslMainFragmentShader_CMO;
+ code[MainFragmentShader_CM] = qopenglslMainFragmentShader_CM;
+ code[MainFragmentShader_MO] = qopenglslMainFragmentShader_MO;
+ code[MainFragmentShader_M] = qopenglslMainFragmentShader_M;
+ code[MainFragmentShader_CO] = qopenglslMainFragmentShader_CO;
+ code[MainFragmentShader_C] = qopenglslMainFragmentShader_C;
+ code[MainFragmentShader_O] = qopenglslMainFragmentShader_O;
+ code[MainFragmentShader] = qopenglslMainFragmentShader;
+ code[MainFragmentShader_ImageArrays] = qopenglslMainFragmentShader_ImageArrays;
+
+ code[ImageSrcFragmentShader] = qopenglslImageSrcFragmentShader;
+ code[ImageSrcWithPatternFragmentShader] = qopenglslImageSrcWithPatternFragmentShader;
+ code[NonPremultipliedImageSrcFragmentShader] = qopenglslNonPremultipliedImageSrcFragmentShader;
+ 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] = ""; //###
+
+ 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 (qShaderSnippets[i] == 0) {
+ qFatal("Shader snippet for %s (#%d) is missing!",
+ snippetNameStr(SnippetName(i)).constData(), i);
+ }
+ }
+#endif
+ snippetsPopulated = true;
+ }
+
+ QOpenGLShader* fragShader;
+ QOpenGLShader* 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 QOpenGLShaderProgram;
+
+ CachedShader simpleShaderCache(fragSource, vertexSource);
+
+ bool inCache = simpleShaderCache.load(simpleShaderProg, context);
+
+ if (!inCache) {
+ vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
+ shaders.append(vertexShader);
+ if (!vertexShader->compileSourceCode(vertexSource))
+ qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
+
+ fragShader = new QOpenGLShader(QOpenGLShader::Fragment);
+ 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 (simpleShaderProg->isLinked()) {
+ if (!inCache)
+ simpleShaderCache.store(simpleShaderProg, context);
+ } else {
+ qCritical() << "Errors linking simple shader:"
+ << simpleShaderProg->log();
+ }
+
+ // 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) {
+ vertexShader = new QOpenGLShader(QOpenGLShader::Vertex);
+ shaders.append(vertexShader);
+ if (!vertexShader->compileSourceCode(vertexSource))
+ qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
+
+ fragShader = new QOpenGLShader(QOpenGLShader::Fragment);
+ 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 (blitShaderProg->isLinked()) {
+ if (!inCache)
+ blitShaderCache.store(blitShaderProg, context);
+ } else {
+ qCritical() << "Errors linking blit shader:"
+ << blitShaderProg->log();
+ }
+
+#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(shaders);
+ shaders.clear();
+
+ qDeleteAll(cachedPrograms);
+ cachedPrograms.clear();
+
+ if (blitShaderProg) {
+ delete blitShaderProg;
+ blitShaderProg = 0;
+ }
+
+ if (simpleShaderProg) {
+ delete simpleShaderProg;
+ simpleShaderProg = 0;
+ }
+}
+
+#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;
+ vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
+ vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
+
+ QScopedPointer<QOpenGLShaderProgram> shaderProgram(new QOpenGLShaderProgram);
+
+ CachedShader shaderCache(fragSource, vertexSource);
+ bool inCache = shaderCache.load(shaderProgram.data(), QOpenGLContext::currentContext());
+
+ if (!inCache) {
+
+ QScopedPointer<QOpenGLShader> fragShader(new QOpenGLShader(QOpenGLShader::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<QOpenGLShader> vertexShader(new QOpenGLShader(QOpenGLShader::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 QOpenGLEngineShaderProg(prog));
+ newProg->program = shaderProgram.take();
+
+ newProg->program->link();
+ if (newProg->program->isLinked()) {
+ if (!inCache)
+ shaderCache.store(newProg->program, QOpenGLContext::currentContext());
+ } else {
+ QLatin1String none("none");
+ QLatin1String br("\n");
+ QString error;
+ error = QLatin1String("Shader program failed to link,");
+#if defined(QT_DEBUG)
+ error += QLatin1String("\n Shaders Used:\n");
+ for (int i = 0; i < newProg->program->shaders().count(); ++i) {
+ QOpenGLShader *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 != 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)
+{
+ // Remove any shader programs which has this as the custom shader src:
+ for (int i = 0; i < cachedPrograms.size(); ++i) {
+ QOpenGLEngineShaderProg *cachedProg = cachedPrograms[i];
+ if (cachedProg->customStageSource == stage->source()) {
+ delete cachedProg;
+ cachedPrograms.removeAt(i);
+ i--;
+ }
+ }
+}
+
+
+QOpenGLEngineShaderManager::QOpenGLEngineShaderManager(QOpenGLContext* context)
+ : ctx(context),
+ shaderProgNeedsChanging(true),
+ complexGeometry(false),
+ srcPixelType(Qt::NoBrush),
+ opacityMode(NoOpacity),
+ maskType(NoMask),
+ compositionMode(QPainter::CompositionMode_SourceOver),
+ customSrcStage(0),
+ currentShaderProg(0)
+{
+ 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);
+
+ static const char *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"
+ };
+
+ 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;
+
+ compositionMode = mode;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QOpenGLEngineShaderManager::setCustomStage(QOpenGLCustomShaderStage* stage)
+{
+ if (customSrcStage)
+ removeCustomStage();
+ customSrcStage = stage;
+ shaderProgNeedsChanging = true;
+}
+
+void QOpenGLEngineShaderManager::removeCustomStage()
+{
+ if (customSrcStage)
+ customSrcStage->setInactive();
+ customSrcStage = 0;
+ 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 true if program needed changing.
+bool QOpenGLEngineShaderManager::useCorrectShaderProg()
+{
+ if (!shaderProgNeedsChanging)
+ return false;
+
+ bool useCustomSrc = customSrcStage != 0;
+ 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::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 (hasCompose && hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CMO;
+ if (hasCompose && hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CM;
+ if (!hasCompose && hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_MO;
+ if (!hasCompose && hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_M;
+ if (hasCompose && !hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_CO;
+ if (hasCompose && !hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_C;
+ if (!hasCompose && !hasMask && useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader_O;
+ if (!hasCompose && !hasMask && !useGlobalOpacity)
+ requiredProgram.mainFragShader = QOpenGLEngineSharedShaders::MainFragmentShader;
+ }
+
+ if (hasMask) {
+ if (maskType == PixelMask) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::MaskFragmentShader;
+ texCoords = true;
+ } else if (maskType == SubPixelMaskPass1) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
+ texCoords = true;
+ } else if (maskType == SubPixelMaskPass2) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
+ texCoords = true;
+ } else if (maskType == SubPixelWithGammaMask) {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
+ texCoords = true;
+ } else {
+ qCritical("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
+ }
+ } else {
+ requiredProgram.maskFragShader = QOpenGLEngineSharedShaders::NoMaskFragmentShader;
+ }
+
+ if (hasCompose) {
+ switch (compositionMode) {
+ case QPainter::CompositionMode_Multiply:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Screen:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Overlay:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Darken:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Lighten:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::LightenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_HardLight:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Difference:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
+ break;
+ default:
+ qWarning("QOpenGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
+ }
+ } else {
+ requiredProgram.compositionFragShader = QOpenGLEngineSharedShaders::NoCompositionModeFragmentShader;
+ }
+
+ // Choose vertex shader main function
+ if (opacityMode == AttributeOpacity) {
+ Q_ASSERT(texCoords);
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
+ } else if (texCoords) {
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainWithTexCoordsVertexShader;
+ } else {
+ requiredProgram.mainVertexShader = QOpenGLEngineSharedShaders::MainVertexShader;
+ }
+ requiredProgram.useTextureCoords = texCoords;
+ requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
+ if (complexGeometry && srcPixelType == Qt::SolidPattern) {
+ requiredProgram.positionVertexShader = QOpenGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader;
+ requiredProgram.usePmvMatrixAttribute = false;
+ } else {
+ requiredProgram.usePmvMatrixAttribute = true;
+
+ // Force complexGeometry off, since we currently don't support that mode for
+ // non-solid brushes
+ complexGeometry = false;
+ }
+
+ // At this point, requiredProgram is fully populated so try to find the program in the cache
+ currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
+
+ if (currentShaderProg && useCustomSrc) {
+ customSrcStage->setUniforms(currentShaderProg->program);
+ }
+
+ // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it
+ // doesn't use are disabled)
+ QOpenGLContextPrivate* ctx_d = ctx->d_func();
+ QOpenGL2PaintEngineEx *active_engine = static_cast<QOpenGL2PaintEngineEx *>(ctx_d->active_engine);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
+ active_engine->d_func()->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
+
+ shaderProgNeedsChanging = false;
+ return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglengineshadermanager_p.h b/src/gui/opengl/qopenglengineshadermanager_p.h
new file mode 100644
index 0000000000..1dcc4fe7a7
--- /dev/null
+++ b/src/gui/opengl/qopenglengineshadermanager_p.h
@@ -0,0 +1,514 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/*
+ VERTEX SHADERS
+ ==============
+
+ Vertex shaders are specified as multiple (partial) shaders. On desktop,
+ this works fine. On ES, QOpenGLShader & QOpenGLShaderProgram will make partial
+ shaders work by concatenating the source in each QOpenGLShader and compiling
+ it as a single shader. This is abstracted nicely by QOpenGLShaderProgram and
+ the GL2 engine doesn't need to worry about it.
+
+ Generally, there's two vertex shader objects. The position shaders are
+ the ones which set gl_Position. There's also two "main" vertex shaders,
+ one which just calls the position shader and another which also passes
+ through some texture coordinates from a vertex attribute array to a
+ varying. These texture coordinates are used for mask position in text
+ rendering and for the source coordinates in drawImage/drawPixmap. There's
+ also a "Simple" vertex shader for rendering a solid colour (used to render
+ into the stencil buffer where the actual colour value is discarded).
+
+ The position shaders for brushes look scary. This is because many of the
+ calculations which logically belong in the fragment shader have been moved
+ into the vertex shader to improve performance. This is why the position
+ calculation is in a separate shader. Not only does it calculate the
+ position, but it also calculates some data to be passed to the fragment
+ shader as a varying. It is optimal to move as much of the calculation as
+ possible into the vertex shader as this is executed less often.
+
+ The varyings passed to the fragment shaders are interpolated (which is
+ cheap). Unfortunately, GL will apply perspective correction to the
+ interpolation calusing errors. To get around this, the vertex shader must
+ apply perspective correction itself and set the w-value of gl_Position to
+ zero. That way, GL will be tricked into thinking it doesn't need to apply a
+ perspective correction and use linear interpolation instead (which is what
+ we want). Of course, if the brush transform is affeine, no perspective
+ correction is needed and a simpler vertex shader can be used instead.
+
+ So there are the following "main" vertex shaders:
+ qopenglslMainVertexShader
+ qopenglslMainWithTexCoordsVertexShader
+
+ And the the following position vertex shaders:
+ qopenglslPositionOnlyVertexShader
+ qopenglslPositionWithTextureBrushVertexShader
+ qopenglslPositionWithPatternBrushVertexShader
+ qopenglslPositionWithLinearGradientBrushVertexShader
+ qopenglslPositionWithRadialGradientBrushVertexShader
+ qopenglslPositionWithConicalGradientBrushVertexShader
+ qopenglslAffinePositionWithTextureBrushVertexShader
+ qopenglslAffinePositionWithPatternBrushVertexShader
+ qopenglslAffinePositionWithLinearGradientBrushVertexShader
+ qopenglslAffinePositionWithRadialGradientBrushVertexShader
+ qopenglslAffinePositionWithConicalGradientBrushVertexShader
+
+ Leading to 23 possible vertex shaders
+
+
+ FRAGMENT SHADERS
+ ================
+
+ Fragment shaders are also specified as multiple (partial) shaders. The
+ different fragment shaders represent the different stages in Qt's fragment
+ pipeline. There are 1-3 stages in this pipeline: First stage is to get the
+ fragment's colour value. The next stage is to get the fragment's mask value
+ (coverage value for anti-aliasing) and the final stage is to blend the
+ incoming fragment with the background (for composition modes not supported
+ by GL).
+
+ Of these, the first stage will always be present. If Qt doesn't need to
+ apply anti-aliasing (because it's off or handled by multisampling) then
+ the coverage value doesn't need to be applied. (Note: There are two types
+ of mask, one for regular anti-aliasing and one for sub-pixel anti-
+ aliasing.) If the composition mode is one which GL supports natively then
+ the blending stage doesn't need to be applied.
+
+ As eash stage can have multiple implementations, they are abstracted as
+ GLSL function calls with the following signatures:
+
+ Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()":
+ qopenglslImageSrcFragShader
+ qopenglslImageSrcWithPatternFragShader
+ qopenglslNonPremultipliedImageSrcFragShader
+ qopenglslSolidBrushSrcFragShader
+ qopenglslTextureBrushSrcFragShader
+ qopenglslTextureBrushWithPatternFragShader
+ qopenglslPatternBrushSrcFragShader
+ qopenglslLinearGradientBrushSrcFragShader
+ qopenglslRadialGradientBrushSrcFragShader
+ qopenglslConicalGradientBrushSrcFragShader
+ NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
+
+ Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
+ qopenglslMaskFragmentShader
+ qopenglslRgbMaskFragmentShaderPass1
+ qopenglslRgbMaskFragmentShaderPass2
+ qopenglslRgbMaskWithGammaFragmentShader
+
+ Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
+ qopenglslColorBurnCompositionModeFragmentShader
+ qopenglslColorDodgeCompositionModeFragmentShader
+ qopenglslDarkenCompositionModeFragmentShader
+ qopenglslDifferenceCompositionModeFragmentShader
+ qopenglslExclusionCompositionModeFragmentShader
+ qopenglslHardLightCompositionModeFragmentShader
+ qopenglslLightenCompositionModeFragmentShader
+ qopenglslMultiplyCompositionModeFragmentShader
+ qopenglslOverlayCompositionModeFragmentShader
+ qopenglslScreenCompositionModeFragmentShader
+ qopenglslSoftLightCompositionModeFragmentShader
+
+
+ Note: In the future, some GLSL compilers will support an extension allowing
+ a new 'color' precision specifier. To support this, qcolorp is used for
+ all color components so it can be defined to colorp or lowp depending upon
+ the implementation.
+
+ So there are differnt frament shader main functions, depending on the
+ number & type of pipelines the fragment needs to go through.
+
+ The choice of which main() fragment shader string to use depends on:
+ - Use of global opacity
+ - Brush style (some brushes apply opacity themselves)
+ - Use & type of mask (TODO: Need to support high quality anti-aliasing & text)
+ - Use of non-GL Composition mode
+
+ Leading to the following fragment shader main functions:
+ gl_FragColor = compose(applyMask(srcPixel()*globalOpacity));
+ gl_FragColor = compose(applyMask(srcPixel()));
+ gl_FragColor = applyMask(srcPixel()*globalOpacity);
+ gl_FragColor = applyMask(srcPixel());
+ gl_FragColor = compose(srcPixel()*globalOpacity);
+ gl_FragColor = compose(srcPixel());
+ gl_FragColor = srcPixel()*globalOpacity;
+ gl_FragColor = srcPixel();
+
+ Called:
+ qopenglslMainFragmentShader_CMO
+ qopenglslMainFragmentShader_CM
+ qopenglslMainFragmentShader_MO
+ qopenglslMainFragmentShader_M
+ qopenglslMainFragmentShader_CO
+ qopenglslMainFragmentShader_C
+ qopenglslMainFragmentShader_O
+ qopenglslMainFragmentShader
+
+ Where:
+ M = Mask
+ C = Composition
+ O = Global Opacity
+
+
+ CUSTOM SHADER CODE
+ ==================
+
+ The use of custom shader code is supported by the engine for drawImage and
+ drawPixmap calls. This is implemented via hooks in the fragment pipeline.
+
+ The custom shader is passed to the engine as a partial fragment shader
+ (QOpenGLCustomShaderStage). The shader will implement a pre-defined method name
+ which Qt's fragment pipeline will call:
+
+ lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords)
+
+ The provided src and srcCoords parameters can be used to sample from the
+ source image.
+
+ Transformations, clipping, opacity, and composition modes set using QPainter
+ will be respected when using the custom shader hook.
+*/
+
+#ifndef QOPENGLENGINE_SHADER_MANAGER_H
+#define QOPENGLENGINE_SHADER_MANAGER_H
+
+#include <QOpenGLShader>
+#include <QOpenGLShaderProgram>
+#include <QPainter>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglcustomshaderstage_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+
+/*
+struct QOpenGLEngineCachedShaderProg
+{
+ QOpenGLEngineCachedShaderProg(QOpenGLEngineShaderManager::ShaderName vertexMain,
+ QOpenGLEngineShaderManager::ShaderName vertexPosition,
+ QOpenGLEngineShaderManager::ShaderName fragMain,
+ QOpenGLEngineShaderManager::ShaderName pixelSrc,
+ QOpenGLEngineShaderManager::ShaderName mask,
+ QOpenGLEngineShaderManager::ShaderName composition);
+
+ int cacheKey;
+ QOpenGLShaderProgram* program;
+}
+*/
+
+static const GLuint QT_VERTEX_COORDS_ATTR = 0;
+static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
+static const GLuint QT_OPACITY_ATTR = 2;
+static const GLuint QT_PMV_MATRIX_1_ATTR = 3;
+static const GLuint QT_PMV_MATRIX_2_ATTR = 4;
+static const GLuint QT_PMV_MATRIX_3_ATTR = 5;
+
+class QOpenGLEngineShaderProg;
+
+class Q_GUI_EXPORT QOpenGLEngineSharedShaders
+{
+ Q_GADGET
+public:
+
+ enum SnippetName {
+ MainVertexShader,
+ MainWithTexCoordsVertexShader,
+ MainWithTexCoordsAndOpacityVertexShader,
+
+ // UntransformedPositionVertexShader must be first in the list:
+ UntransformedPositionVertexShader,
+ PositionOnlyVertexShader,
+ ComplexGeometryPositionOnlyVertexShader,
+ PositionWithPatternBrushVertexShader,
+ PositionWithLinearGradientBrushVertexShader,
+ PositionWithConicalGradientBrushVertexShader,
+ PositionWithRadialGradientBrushVertexShader,
+ PositionWithTextureBrushVertexShader,
+ AffinePositionWithPatternBrushVertexShader,
+ AffinePositionWithLinearGradientBrushVertexShader,
+ AffinePositionWithConicalGradientBrushVertexShader,
+ AffinePositionWithRadialGradientBrushVertexShader,
+ AffinePositionWithTextureBrushVertexShader,
+
+ // MainFragmentShader_CMO must be first in the list:
+ MainFragmentShader_CMO,
+ MainFragmentShader_CM,
+ MainFragmentShader_MO,
+ MainFragmentShader_M,
+ MainFragmentShader_CO,
+ MainFragmentShader_C,
+ MainFragmentShader_O,
+ MainFragmentShader,
+ MainFragmentShader_ImageArrays,
+
+ // ImageSrcFragmentShader must be first in the list::
+ ImageSrcFragmentShader,
+ ImageSrcWithPatternFragmentShader,
+ NonPremultipliedImageSrcFragmentShader,
+ CustomImageSrcFragmentShader,
+ SolidBrushSrcFragmentShader,
+ TextureBrushSrcFragmentShader,
+ TextureBrushSrcWithPatternFragmentShader,
+ PatternBrushSrcFragmentShader,
+ LinearGradientBrushSrcFragmentShader,
+ RadialGradientBrushSrcFragmentShader,
+ ConicalGradientBrushSrcFragmentShader,
+ ShockingPinkSrcFragmentShader,
+
+ // NoMaskFragmentShader must be first in the list:
+ NoMaskFragmentShader,
+ MaskFragmentShader,
+ RgbMaskFragmentShaderPass1,
+ RgbMaskFragmentShaderPass2,
+ RgbMaskWithGammaFragmentShader,
+
+ // NoCompositionModeFragmentShader must be first in the list:
+ NoCompositionModeFragmentShader,
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+
+ TotalSnippetCount, InvalidSnippetName
+ };
+#if defined (QT_DEBUG)
+ Q_ENUMS(SnippetName)
+ static QByteArray snippetNameStr(SnippetName snippetName);
+#endif
+
+/*
+ // These allow the ShaderName enum to be used as a cache key
+ const int mainVertexOffset = 0;
+ const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
+ const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
+ const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
+ const int maskOffset = (1<<14) - NoMaskShader;
+ const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
+*/
+
+ QOpenGLEngineSharedShaders(QOpenGLContext *context);
+ ~QOpenGLEngineSharedShaders();
+
+ QOpenGLShaderProgram *simpleProgram() { return simpleShaderProg; }
+ QOpenGLShaderProgram *blitProgram() { return blitShaderProg; }
+ // Compile the program if it's not already in the cache, return the item in the cache.
+ QOpenGLEngineShaderProg *findProgramInCache(const QOpenGLEngineShaderProg &prog);
+ // Compile the custom shader if it's not already in the cache, return the item in the cache.
+
+ static QOpenGLEngineSharedShaders *shadersForContext(QOpenGLContext *context);
+
+ // Ideally, this would be static and cleanup all programs in all contexts which
+ // contain the custom code. Currently it is just a hint and we rely on deleted
+ // custom shaders being cleaned up by being kicked out of the cache when it's
+ // full.
+ void cleanupCustomStage(QOpenGLCustomShaderStage* stage);
+
+private:
+ QOpenGLShaderProgram *blitShaderProg;
+ QOpenGLShaderProgram *simpleShaderProg;
+ QList<QOpenGLEngineShaderProg*> cachedPrograms;
+ QList<QOpenGLShader *> shaders;
+
+ static const char* qShaderSnippets[TotalSnippetCount];
+};
+
+
+class QOpenGLEngineShaderProg
+{
+public:
+ QOpenGLEngineShaderProg() : program(0) {}
+
+ ~QOpenGLEngineShaderProg() {
+ if (program)
+ delete program;
+ }
+
+ QOpenGLEngineSharedShaders::SnippetName mainVertexShader;
+ QOpenGLEngineSharedShaders::SnippetName positionVertexShader;
+ QOpenGLEngineSharedShaders::SnippetName mainFragShader;
+ QOpenGLEngineSharedShaders::SnippetName srcPixelFragShader;
+ QOpenGLEngineSharedShaders::SnippetName maskFragShader;
+ QOpenGLEngineSharedShaders::SnippetName compositionFragShader;
+
+ QByteArray customStageSource; //TODO: Decent cache key for custom stages
+ QOpenGLShaderProgram* program;
+
+ QVector<uint> uniformLocations;
+
+ bool useTextureCoords;
+ bool useOpacityAttribute;
+ bool usePmvMatrixAttribute;
+
+ bool operator==(const QOpenGLEngineShaderProg& other) {
+ // We don't care about the program
+ return ( mainVertexShader == other.mainVertexShader &&
+ positionVertexShader == other.positionVertexShader &&
+ mainFragShader == other.mainFragShader &&
+ srcPixelFragShader == other.srcPixelFragShader &&
+ maskFragShader == other.maskFragShader &&
+ compositionFragShader == other.compositionFragShader &&
+ customStageSource == other.customStageSource
+ );
+ }
+};
+
+class Q_GUI_EXPORT QOpenGLEngineShaderManager : public QObject
+{
+ Q_OBJECT
+public:
+ QOpenGLEngineShaderManager(QOpenGLContext* context);
+ ~QOpenGLEngineShaderManager();
+
+ enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask};
+ enum PixelSrcType {
+ ImageSrc = Qt::TexturePattern+1,
+ NonPremultipliedImageSrc = Qt::TexturePattern+2,
+ PatternSrc = Qt::TexturePattern+3,
+ TextureSrcWithPattern = Qt::TexturePattern+4
+ };
+
+ enum Uniform {
+ ImageTexture,
+ PatternColor,
+ GlobalOpacity,
+ Depth,
+ MaskTexture,
+ FragmentColor,
+ LinearData,
+ Angle,
+ HalfViewportSize,
+ Fmp,
+ Fmp2MRadius2,
+ Inverse2Fmp2MRadius2,
+ SqrFr,
+ BRadius,
+ InvertedTextureSize,
+ BrushTransform,
+ BrushTexture,
+ Matrix,
+ NumUniforms
+ };
+
+ enum OpacityMode {
+ NoOpacity,
+ UniformOpacity,
+ AttributeOpacity
+ };
+
+ // There are optimizations we can do, depending on the brush transform:
+ // 1) May not have to apply perspective-correction
+ // 2) Can use lower precision for matrix
+ void optimiseForBrushTransform(QTransform::TransformationType transformType);
+ void setSrcPixelType(Qt::BrushStyle);
+ void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
+ void setOpacityMode(OpacityMode);
+ void setMaskType(MaskType);
+ void setCompositionMode(QPainter::CompositionMode);
+ void setCustomStage(QOpenGLCustomShaderStage* stage);
+ void removeCustomStage();
+
+ GLuint getUniformLocation(Uniform id);
+
+ void setDirty(); // someone has manually changed the current shader program
+ bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
+
+ void useSimpleProgram();
+ void useBlitProgram();
+ void setHasComplexGeometry(bool hasComplexGeometry)
+ {
+ complexGeometry = hasComplexGeometry;
+ shaderProgNeedsChanging = true;
+ }
+ bool hasComplexGeometry() const
+ {
+ return complexGeometry;
+ }
+
+ QOpenGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
+ QOpenGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
+ QOpenGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
+
+ QOpenGLEngineSharedShaders* sharedShaders;
+
+private:
+ QOpenGLContext* ctx;
+ bool shaderProgNeedsChanging;
+ bool complexGeometry;
+
+ // Current state variables which influence the choice of shader:
+ QTransform brushTransform;
+ int srcPixelType;
+ OpacityMode opacityMode;
+ MaskType maskType;
+ QPainter::CompositionMode compositionMode;
+ QOpenGLCustomShaderStage* customSrcStage;
+
+ QOpenGLEngineShaderProg* currentShaderProg;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QOPENGLENGINE_SHADER_MANAGER_H
diff --git a/src/gui/opengl/qopenglengineshadersource_p.h b/src/gui/opengl/qopenglengineshadersource_p.h
new file mode 100644
index 0000000000..cb85212308
--- /dev/null
+++ b/src/gui/opengl/qopenglengineshadersource_p.h
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef QOPENGL_ENGINE_SHADER_SOURCE_H
+#define QOPENGL_ENGINE_SHADER_SOURCE_H
+
+#include "qopenglengineshadermanager_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+
+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 highp 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 highp 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;
+
+#if defined(QT_OPENGL_ES_2)
+// 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 qopenglslTextureBrushSrcFragmentShader = "\n\
+ varying highp vec2 brushTextureCoords; \n\
+ uniform sampler2D brushTexture; \n\
+ lowp vec4 srcPixel() { \n\
+ return texture2D(brushTexture, fract(brushTextureCoords)); \n\
+ }\n";
+#else
+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";
+#endif
+
+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 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_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 qopenglslMainFragmentShader_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 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_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 qopenglslMainFragmentShader_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 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";
+
+/*
+ Left to implement:
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+*/
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/gui/opengl/qopenglextensions_p.h b/src/gui/opengl/qopenglextensions_p.h
new file mode 100644
index 0000000000..a4d88a059e
--- /dev/null
+++ b/src/gui/opengl/qopenglextensions_p.h
@@ -0,0 +1,676 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGL_EXTENSIONS_P_H
+#define QOPENGL_EXTENSIONS_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 "qopenglfunctions.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if 0
+#ifndef GL_ARB_vertex_buffer_object
+typedef ptrdiff_t GLintptrARB;
+typedef ptrdiff_t GLsizeiptrARB;
+#endif
+#endif
+
+#ifndef GL_VERSION_2_0
+typedef char GLchar;
+#endif
+
+struct QOpenGLExtensionsPrivate;
+
+class Q_GUI_EXPORT QOpenGLExtensions : public QOpenGLFunctions
+{
+ Q_DECLARE_PRIVATE(QOpenGLExtensions)
+public:
+ QOpenGLExtensions();
+ QOpenGLExtensions(QOpenGLContext *context);
+ ~QOpenGLExtensions() {}
+
+ enum OpenGLExtension {
+ TextureRectangle = 0x00000001,
+ GenerateMipmap = 0x00000002,
+ TextureCompression = 0x00000004,
+ MirroredRepeat = 0x00000008,
+ FramebufferMultisample = 0x00000010,
+ StencilTwoSide = 0x00000020,
+ StencilWrap = 0x00000040,
+ PackedDepthStencil = 0x00000080,
+ NVFloatBuffer = 0x00000100,
+ PixelBufferObject = 0x00000200,
+ FramebufferBlit = 0x00000400,
+ BGRATextureFormat = 0x00000800,
+ DDSTextureCompression = 0x00001000,
+ ETC1TextureCompression = 0x00002000,
+ PVRTCTextureCompression = 0x00004000,
+ ElementIndexUint = 0x00008000,
+ Depth24 = 0x00010000,
+ SRGBFrameBuffer = 0x00020000,
+ MapBuffer = 0x00040000,
+ GeometryShaders = 0x00080000
+ };
+ Q_DECLARE_FLAGS(OpenGLExtensions, OpenGLExtension)
+
+ OpenGLExtensions openGLExtensions();
+ bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const;
+
+ void initializeGLExtensions();
+
+ GLvoid *glMapBuffer(GLenum target, GLenum access);
+ GLboolean glUnmapBuffer(GLenum target);
+
+ void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+
+ void glRenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height);
+
+ void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+
+private:
+ static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; }
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLExtensions::OpenGLExtensions)
+
+struct QOpenGLExtensionsPrivate : public QOpenGLFunctionsPrivate
+{
+ QOpenGLExtensionsPrivate(QOpenGLContext *ctx);
+
+ GLvoid* (QOPENGLF_APIENTRYP MapBuffer)(GLenum target, GLenum access);
+ GLboolean (QOPENGLF_APIENTRYP UnmapBuffer)(GLenum target);
+ void (QOPENGLF_APIENTRYP BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
+ void (QOPENGLF_APIENTRYP RenderbufferStorageMultisample)(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height);
+ void (QOPENGLF_APIENTRYP GetBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data);
+};
+
+inline GLvoid *QOpenGLExtensions::glMapBuffer(GLenum target, GLenum access)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ GLvoid *result = d->MapBuffer(target, access);
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLboolean QOpenGLExtensions::glUnmapBuffer(GLenum target)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ GLboolean result = d->UnmapBuffer(target);
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLExtensions::glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ d->BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtensions::glRenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ d->RenderbufferStorageMultisample(target, samples, internalFormat, width, height);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtensions::glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)
+{
+ Q_D(QOpenGLExtensions);
+ Q_ASSERT(QOpenGLExtensions::isInitialized(d));
+ d->GetBufferSubData(target, offset, size, data);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE
+#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA
+#endif
+#ifndef GL_FRAMEBUFFER_SRGB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+#ifndef GL_ARRAY_BUFFER
+#define GL_ARRAY_BUFFER 0x8892
+#endif
+#ifndef GL_STATIC_DRAW
+#define GL_STATIC_DRAW 0x88E4
+#endif
+#ifndef GL_TEXTURE_RECTANGLE
+#define GL_TEXTURE_RECTANGLE 0x84F5
+#endif
+#ifndef GL_TEXTURE_BINDING_RECTANGLE
+#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6
+#endif
+#ifndef GL_PROXY_TEXTURE_RECTANGLE
+#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7
+#endif
+#ifndef GL_MAX_RECTANGLE_TEXTURE_SIZE
+#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8
+#endif
+#ifndef GL_BGRA
+#define GL_BGRA 0x80E1
+#endif
+#ifndef GL_RGB16
+#define GL_RGB16 0x8054
+#endif
+#ifndef GL_UNSIGNED_SHORT_5_6_5
+#define GL_UNSIGNED_SHORT_5_6_5 0x8363
+#endif
+#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
+#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
+#endif
+#ifndef GL_MULTISAMPLE
+#define GL_MULTISAMPLE 0x809D
+#endif
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+#ifndef GL_MIRRORED_REPEAT
+#define GL_MIRRORED_REPEAT 0x8370
+#endif
+#ifndef GL_GENERATE_MIPMAP
+#define GL_GENERATE_MIPMAP 0x8191
+#endif
+#ifndef GL_GENERATE_MIPMAP_HINT
+#define GL_GENERATE_MIPMAP_HINT 0x8192
+#endif
+#ifndef GL_FRAGMENT_PROGRAM
+#define GL_FRAGMENT_PROGRAM 0x8804
+#endif
+#ifndef GL_PROGRAM_FORMAT_ASCII
+#define GL_PROGRAM_FORMAT_ASCII 0x8875
+#endif
+#ifndef GL_PIXEL_UNPACK_BUFFER
+#define GL_PIXEL_UNPACK_BUFFER 0x88EC
+#endif
+#ifndef GL_WRITE_ONLY
+#define GL_WRITE_ONLY 0x88B9
+#endif
+#ifndef GL_STREAM_DRAW
+#define GL_STREAM_DRAW 0x88E0
+#endif
+#ifndef GL_STENCIL_TEST_TWO_SIDE
+#define GL_STENCIL_TEST_TWO_SIDE 0x8910
+#endif
+#ifndef GL_INCR_WRAP
+#define GL_INCR_WRAP 0x8507
+#endif
+#ifndef GL_DECR_WRAP
+#define GL_DECR_WRAP 0x8508
+#endif
+#ifndef GL_TEXTURE0
+#define GL_TEXTURE0 0x84C0
+#endif
+#ifndef GL_TEXTURE1
+#define GL_TEXTURE1 0x84C1
+#endif
+#ifndef GL_DEPTH_COMPONENT16
+#define GL_DEPTH_COMPONENT16 0x81A5
+#endif
+#ifndef GL_DEPTH_COMPONENT24
+#define GL_DEPTH_COMPONENT24 0x81A6
+#endif
+#ifndef GL_INVALID_FRAMEBUFFER_OPERATION
+#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
+#endif
+#ifndef GL_MAX_RENDERBUFFER_SIZE
+#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
+#endif
+#ifndef GL_FRAMEBUFFER_BINDING
+#define GL_FRAMEBUFFER_BINDING 0x8CA6
+#endif
+#ifndef GL_RENDERBUFFER_BINDING
+#define GL_RENDERBUFFER_BINDING 0x8CA7
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET 0x8CD4
+#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_MISSING_ATTACHMENT
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT
+#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT 0x8CD8
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
+#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS 0x8CDA
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
+#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
+#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
+#endif
+#ifndef GL_FRAMEBUFFER_UNSUPPORTED
+#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
+#endif
+#ifndef GL_MAX_COLOR_ATTACHMENTS
+#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
+#endif
+#ifndef GL_COLOR_ATTACHMENT0
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#endif
+#ifndef GL_COLOR_ATTACHMENT1
+#define GL_COLOR_ATTACHMENT1 0x8CE1
+#endif
+#ifndef GL_COLOR_ATTACHMENT2
+#define GL_COLOR_ATTACHMENT2 0x8CE2
+#endif
+#ifndef GL_COLOR_ATTACHMENT3
+#define GL_COLOR_ATTACHMENT3 0x8CE3
+#endif
+#ifndef GL_COLOR_ATTACHMENT4
+#define GL_COLOR_ATTACHMENT4 0x8CE4
+#endif
+#ifndef GL_COLOR_ATTACHMENT5
+#define GL_COLOR_ATTACHMENT5 0x8CE5
+#endif
+#ifndef GL_COLOR_ATTACHMENT6
+#define GL_COLOR_ATTACHMENT6 0x8CE6
+#endif
+#ifndef GL_COLOR_ATTACHMENT7
+#define GL_COLOR_ATTACHMENT7 0x8CE7
+#endif
+#ifndef GL_COLOR_ATTACHMENT8
+#define GL_COLOR_ATTACHMENT8 0x8CE8
+#endif
+#ifndef GL_COLOR_ATTACHMENT9
+#define GL_COLOR_ATTACHMENT9 0x8CE9
+#endif
+#ifndef GL_COLOR_ATTACHMENT10
+#define GL_COLOR_ATTACHMENT10 0x8CEA
+#endif
+#ifndef GL_COLOR_ATTACHMENT11
+#define GL_COLOR_ATTACHMENT11 0x8CEB
+#endif
+#ifndef GL_COLOR_ATTACHMENT12
+#define GL_COLOR_ATTACHMENT12 0x8CEC
+#endif
+#ifndef GL_COLOR_ATTACHMENT13
+#define GL_COLOR_ATTACHMENT13 0x8CED
+#endif
+#ifndef GL_COLOR_ATTACHMENT14
+#define GL_COLOR_ATTACHMENT14 0x8CEE
+#endif
+#ifndef GL_COLOR_ATTACHMENT15
+#define GL_COLOR_ATTACHMENT15 0x8CEF
+#endif
+#ifndef GL_DEPTH_ATTACHMENT
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#endif
+#ifndef GL_STENCIL_ATTACHMENT
+#define GL_STENCIL_ATTACHMENT 0x8D20
+#endif
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER 0x8D40
+#endif
+#ifndef GL_RENDERBUFFER
+#define GL_RENDERBUFFER 0x8D41
+#endif
+#ifndef GL_RENDERBUFFER_WIDTH
+#define GL_RENDERBUFFER_WIDTH 0x8D42
+#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_STENCIL_INDEX
+#define GL_STENCIL_INDEX 0x8D45
+#endif
+#ifndef GL_STENCIL_INDEX1
+#define GL_STENCIL_INDEX1 0x8D46
+#endif
+#ifndef GL_STENCIL_INDEX4
+#define GL_STENCIL_INDEX4 0x8D47
+#endif
+#ifndef GL_STENCIL_INDEX8
+#define GL_STENCIL_INDEX8 0x8D48
+#endif
+#ifndef GL_STENCIL_INDEX16
+#define GL_STENCIL_INDEX16 0x8D49
+#endif
+#ifndef GL_RENDERBUFFER_RED_SIZE
+#define GL_RENDERBUFFER_RED_SIZE 0x8D50
+#endif
+#ifndef GL_RENDERBUFFER_GREEN_SIZE
+#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
+#endif
+#ifndef GL_RENDERBUFFER_BLUE_SIZE
+#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
+#endif
+#ifndef GL_RENDERBUFFER_ALPHA_SIZE
+#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
+#endif
+#ifndef GL_RENDERBUFFER_DEPTH_SIZE
+#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
+#endif
+#ifndef GL_RENDERBUFFER_STENCIL_SIZE
+#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
+#endif
+#ifndef GL_READ_FRAMEBUFFER
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#endif
+#ifndef GL_RENDERBUFFER_SAMPLES
+#define GL_RENDERBUFFER_SAMPLES 0x8CAB
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
+#endif
+#ifndef GL_MAX_SAMPLES
+#define GL_MAX_SAMPLES 0x8D57
+#endif
+#ifndef GL_DRAW_FRAMEBUFFER
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+#ifndef GL_UNSIGNED_INT_24_8
+#define GL_UNSIGNED_INT_24_8 0x84FA
+#endif
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+#ifndef GL_TEXTURE_STENCIL_SIZE
+#define GL_TEXTURE_STENCIL_SIZE 0x88F1
+#endif
+#ifndef GL_CLAMP_TO_EDGE
+#define GL_CLAMP_TO_EDGE 0x812F
+#endif
+#ifndef GL_PACK_SKIP_IMAGES
+#define GL_PACK_SKIP_IMAGES 0x806B
+#endif
+#ifndef GL_PACK_IMAGE_HEIGHT
+#define GL_PACK_IMAGE_HEIGHT 0x806C
+#endif
+#ifndef GL_UNPACK_SKIP_IMAGES
+#define GL_UNPACK_SKIP_IMAGES 0x806D
+#endif
+#ifndef GL_UNPACK_IMAGE_HEIGHT
+#define GL_UNPACK_IMAGE_HEIGHT 0x806E
+#endif
+#ifndef GL_CONSTANT_COLOR
+#define GL_CONSTANT_COLOR 0x8001
+#endif
+#ifndef GL_ONE_MINUS_CONSTANT_COLOR
+#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
+#endif
+#ifndef GL_CONSTANT_ALPHA
+#define GL_CONSTANT_ALPHA 0x8003
+#endif
+#ifndef GL_ONE_MINUS_CONSTANT_ALPHA
+#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
+#endif
+#ifndef GL_INCR_WRAP
+#define GL_INCR_WRAP 0x8507
+#endif
+#ifndef GL_DECR_WRAP
+#define GL_DECR_WRAP 0x8508
+#endif
+#ifndef GL_ARRAY_BUFFER
+#define GL_ARRAY_BUFFER 0x8892
+#endif
+#ifndef GL_ELEMENT_ARRAY_BUFFER
+#define GL_ELEMENT_ARRAY_BUFFER 0x8893
+#endif
+#ifndef GL_STREAM_DRAW
+#define GL_STREAM_DRAW 0x88E0
+#endif
+#ifndef GL_STREAM_READ
+#define GL_STREAM_READ 0x88E1
+#endif
+#ifndef GL_STREAM_COPY
+#define GL_STREAM_COPY 0x88E2
+#endif
+#ifndef GL_STATIC_DRAW
+#define GL_STATIC_DRAW 0x88E4
+#endif
+#ifndef GL_STATIC_READ
+#define GL_STATIC_READ 0x88E5
+#endif
+#ifndef GL_STATIC_COPY
+#define GL_STATIC_COPY 0x88E6
+#endif
+#ifndef GL_DYNAMIC_DRAW
+#define GL_DYNAMIC_DRAW 0x88E8
+#endif
+#ifndef GL_DYNAMIC_READ
+#define GL_DYNAMIC_READ 0x88E9
+#endif
+#ifndef GL_DYNAMIC_COPY
+#define GL_DYNAMIC_COPY 0x88EA
+#endif
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#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_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_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_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_SAMPLER_1D
+#define GL_SAMPLER_1D 0x8B5D
+#endif
+#ifndef GL_SAMPLER_2D
+#define GL_SAMPLER_2D 0x8B5E
+#endif
+#ifndef GL_SAMPLER_3D
+#define GL_SAMPLER_3D 0x8B5F
+#endif
+#ifndef GL_SAMPLER_CUBE
+#define GL_SAMPLER_CUBE 0x8B60
+#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_GEOMETRY_SHADER
+#define GL_GEOMETRY_SHADER 0x8DD9
+#endif
+#ifndef GL_GEOMETRY_VERTICES_OUT
+#define GL_GEOMETRY_VERTICES_OUT 0x8DDA
+#endif
+#ifndef GL_GEOMETRY_INPUT_TYPE
+#define GL_GEOMETRY_INPUT_TYPE 0x8DDB
+#endif
+#ifndef GL_GEOMETRY_OUTPUT_TYPE
+#define GL_GEOMETRY_OUTPUT_TYPE 0x8DDC
+#endif
+#ifndef GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS
+#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29
+#endif
+#ifndef GL_MAX_GEOMETRY_VARYING_COMPONENTS
+#define GL_MAX_GEOMETRY_VARYING_COMPONENTS 0x8DDD
+#endif
+#ifndef GL_MAX_VERTEX_VARYING_COMPONENTS
+#define GL_MAX_VERTEX_VARYING_COMPONENTS 0x8DDE
+#endif
+#ifndef GL_MAX_VARYING_COMPONENTS
+#define GL_MAX_VARYING_COMPONENTS 0x8B4B
+#endif
+#ifndef GL_MAX_GEOMETRY_UNIFORM_COMPONENTS
+#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF
+#endif
+#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES
+#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0
+#endif
+#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS
+#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1
+#endif
+#ifndef GL_LINES_ADJACENCY
+#define GL_LINES_ADJACENCY 0xA
+#endif
+#ifndef GL_LINE_STRIP_ADJACENCY
+#define GL_LINE_STRIP_ADJACENCY 0xB
+#endif
+#ifndef GL_TRIANGLES_ADJACENCY
+#define GL_TRIANGLES_ADJACENCY 0xC
+#endif
+#ifndef GL_TRIANGLE_STRIP_ADJACENCY
+#define GL_TRIANGLE_STRIP_ADJACENCY 0xD
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8
+#endif
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT
+#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT 0x8DA9
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_LAYERED
+#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
+#endif
+#ifndef GL_PROGRAM_POINT_SIZE
+#define GL_PROGRAM_POINT_SIZE 0x8642
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOPENGL_EXTENSIONS_P_H
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
new file mode 100644
index 0000000000..543a48fc08
--- /dev/null
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -0,0 +1,1354 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglframebufferobject.h"
+#include "qopenglframebufferobject_p.h"
+
+#include <qdebug.h>
+#include <private/qopengl_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
+#include <private/qfont_p.h>
+#include <private/qpaintengineex_opengl2_p.h>
+
+#include <qwindow.h>
+#include <qlibrary.h>
+#include <qimage.h>
+
+QT_BEGIN_NAMESPACE
+
+#define QOPENGL_FUNC_CONTEXT QOpenGLContext *ctx = QOpenGLContext::currentContext();
+#define QOPENGL_FUNCP_CONTEXT QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+#ifndef QT_NO_DEBUG
+#define QT_RESET_GLERROR() \
+{ \
+ while (glGetError() != GL_NO_ERROR) {} \
+}
+#define QT_CHECK_GLERROR() \
+{ \
+ GLenum err = 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
+
+/*!
+ \class QOpenGLFramebufferObjectFormat
+ \brief The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL
+ framebuffer object.
+
+ \since 4.6
+
+ \ingroup painting-3D
+
+ A framebuffer object has several characteristics:
+ \list
+ \i \link setSamples() Number of samples per pixels.\endlink
+ \i \link setAttachment() Depth and/or stencil attachments.\endlink
+ \i \link setTextureTarget() Texture target.\endlink
+ \i \link setInternalTextureFormat() Internal texture format.\endlink
+ \endlist
+
+ Note that the desired attachments or number of samples per pixels might not
+ be supported by the hardware driver. Call QOpenGLFramebufferObject::format()
+ after creating a QOpenGLFramebufferObject to find the exact format that was
+ used to create the frame buffer object.
+
+ \sa QOpenGLFramebufferObject
+*/
+
+/*!
+ \internal
+*/
+void QOpenGLFramebufferObjectFormat::detach()
+{
+ if (d->ref != 1) {
+ QOpenGLFramebufferObjectFormatPrivate *newd
+ = new QOpenGLFramebufferObjectFormatPrivate(d);
+ if (!d->ref.deref())
+ delete d;
+ d = newd;
+ }
+}
+
+/*!
+ Creates a QOpenGLFramebufferObjectFormat 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()
+*/
+
+QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat()
+{
+ d = new QOpenGLFramebufferObjectFormatPrivate;
+}
+
+/*!
+ Constructs a copy of \a other.
+*/
+
+QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat(const QOpenGLFramebufferObjectFormat &other)
+{
+ d = other.d;
+ d->ref.ref();
+}
+
+/*!
+ Assigns \a other to this object.
+*/
+
+QOpenGLFramebufferObjectFormat &QOpenGLFramebufferObjectFormat::operator=(const QOpenGLFramebufferObjectFormat &other)
+{
+ if (d != other.d) {
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ delete d;
+ d = other.d;
+ }
+ return *this;
+}
+
+/*!
+ Destroys the QOpenGLFramebufferObjectFormat.
+*/
+QOpenGLFramebufferObjectFormat::~QOpenGLFramebufferObjectFormat()
+{
+ 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 can not 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 QOpenGLFramebufferObjectFormat::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 QOpenGLFramebufferObjectFormat::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(), QOpenGLFramebufferObject::texture()
+*/
+void QOpenGLFramebufferObjectFormat::setMipmap(bool enabled)
+{
+ detach();
+ d->mipmap = enabled;
+}
+
+/*!
+ \since 4.8
+
+ Returns true if mipmapping is enabled.
+
+ \sa setMipmap()
+*/
+bool QOpenGLFramebufferObjectFormat::mipmap() const
+{
+ return d->mipmap;
+}
+
+/*!
+ Sets the attachment configuration of a framebuffer object to \a attachment.
+
+ \sa attachment()
+*/
+void QOpenGLFramebufferObjectFormat::setAttachment(QOpenGLFramebufferObject::Attachment attachment)
+{
+ detach();
+ d->attachment = attachment;
+}
+
+/*!
+ Returns the configuration of the depth and stencil buffers attached to
+ a framebuffer object. The default is QOpenGLFramebufferObject::NoAttachment.
+
+ \sa setAttachment()
+*/
+QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObjectFormat::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 QOpenGLFramebufferObjectFormat::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 QOpenGLFramebufferObjectFormat::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 QOpenGLFramebufferObjectFormat::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 QOpenGLFramebufferObjectFormat::internalTextureFormat() const
+{
+ return d->internal_format;
+}
+
+/*!
+ Returns true if all the options of this framebuffer object format
+ are the same as \a other; otherwise returns false.
+*/
+bool QOpenGLFramebufferObjectFormat::operator==(const QOpenGLFramebufferObjectFormat& other) const
+{
+ if (d == other.d)
+ return true;
+ else
+ return d->equals(other.d);
+}
+
+/*!
+ Returns false if all the options of this framebuffer object format
+ are the same as \a other; otherwise returns true.
+*/
+bool QOpenGLFramebufferObjectFormat::operator!=(const QOpenGLFramebufferObjectFormat& other) const
+{
+ return !(*this == other);
+}
+
+void QOpenGLFBOGLPaintDevice::setFBO(QOpenGLFramebufferObject* f,
+ QOpenGLFramebufferObject::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 = QOpenGLContext::currentContext()->format();
+ if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil) {
+ fboFormat.setDepthBufferSize(24);
+ fboFormat.setStencilBufferSize(8);
+ } else if (attachment == QOpenGLFramebufferObject::Depth) {
+ fboFormat.setDepthBufferSize(24);
+ fboFormat.setStencilBufferSize(0);
+ } else {
+ fboFormat.setDepthBufferSize(0);
+ fboFormat.setStencilBufferSize(0);
+ }
+
+ GLenum format = f->format().internalTextureFormat();
+ reqAlpha = (format != GL_RGB
+#ifndef QT_OPENGL_ES
+ && format != GL_RGB5 && format != GL_RGB8
+#endif
+ );
+}
+
+QOpenGLContextGroup *QOpenGLFBOGLPaintDevice::group() const
+{
+ QOpenGLSharedResourceGuard *fbo_guard =
+ fbo->d_func()->fbo_guard;
+ return fbo_guard ? fbo_guard->group() : 0;
+}
+
+bool QOpenGLFramebufferObjectPrivate::checkFramebufferStatus() const
+{
+ QOPENGL_FUNCP_CONTEXT;
+ if (!ctx)
+ return false; // Context no longer exists.
+ GLenum status = QOpenGLFunctions(ctx).glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ switch(status) {
+ case GL_NO_ERROR:
+ case GL_FRAMEBUFFER_COMPLETE:
+ return true;
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED:
+ qDebug("QOpenGLFramebufferObject: Unsupported framebuffer format.");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete attachment.");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.");
+ break;
+#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT
+ case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");
+ break;
+#endif
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");
+ break;
+#if 1
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
+ qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
+ break;
+#endif
+ default:
+ qDebug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status;
+ break;
+ }
+ return false;
+}
+
+namespace
+{
+ void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id)
+ {
+ funcs->glDeleteFramebuffers(1, &id);
+ }
+
+ void freeRenderbufferFunc(QOpenGLFunctions *funcs, GLuint id)
+ {
+ funcs->glDeleteRenderbuffers(1, &id);
+ }
+
+ void freeTextureFunc(QOpenGLFunctions *, GLuint id)
+ {
+ glDeleteTextures(1, &id);
+ }
+}
+
+void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *q, const QSize &sz,
+ QOpenGLFramebufferObject::Attachment attachment,
+ GLenum texture_target, GLenum internal_format,
+ GLint samples, bool mipmap)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ funcs.initializeGLFunctions();
+
+ if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
+ return;
+
+ 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) {
+ glGenTextures(1, &texture);
+ glBindTexture(target, texture);
+ glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ if (mipmap)
+ funcs.glGenerateMipmap(GL_TEXTURE_2D);
+#ifndef QT_OPENGL_ES
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#else
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+#endif
+ funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ target, texture, 0);
+
+ QT_CHECK_GLERROR();
+ valid = checkFramebufferStatus();
+ glBindTexture(target, 0);
+
+ color_buffer = 0;
+ } else {
+ mipmap = false;
+ GLint maxSamples;
+ 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 == QOpenGLFramebufferObject::CombinedDepthStencil
+ && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
+ {
+ // depth and stencil buffer needs another extension
+ funcs.glGenRenderbuffers(1, &depth_buffer);
+ Q_ASSERT(!funcs.glIsRenderbuffer(depth_buffer));
+ funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
+ Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
+ 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);
+
+ valid = checkFramebufferStatus();
+ if (!valid) {
+ funcs.glDeleteRenderbuffers(1, &depth_buffer);
+ stencil_buffer = depth_buffer = 0;
+ }
+ }
+
+ if (depth_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
+ || (attachment == QOpenGLFramebufferObject::Depth)))
+ {
+ funcs.glGenRenderbuffers(1, &depth_buffer);
+ Q_ASSERT(!funcs.glIsRenderbuffer(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, 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,
+ 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 == QOpenGLFramebufferObject::CombinedDepthStencil)) {
+ funcs.glGenRenderbuffers(1, &stencil_buffer);
+ Q_ASSERT(!funcs.glIsRenderbuffer(stencil_buffer));
+ funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer);
+ Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));
+ if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
+#ifdef QT_OPENGL_ES
+ funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+ GL_STENCIL_INDEX8, size.width(), size.height());
+#else
+ funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
+ GL_STENCIL_INDEX, size.width(), size.height());
+#endif
+ } else {
+#ifdef QT_OPENGL_ES
+ funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
+ size.width(), size.height());
+#else
+ funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX,
+ size.width(), size.height());
+#endif
+ }
+ 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 = QOpenGLFramebufferObject::CombinedDepthStencil;
+ } else if (depth_buffer) {
+ fbo_attachment = QOpenGLFramebufferObject::Depth;
+ } else {
+ fbo_attachment = QOpenGLFramebufferObject::NoAttachment;
+ }
+
+ funcs.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
+ if (valid) {
+ fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
+ if (color_buffer)
+ color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
+ else
+ texture_guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc);
+ if (depth_buffer)
+ depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
+ if (stencil_buffer) {
+ if (stencil_buffer == depth_buffer)
+ stencil_buffer_guard = depth_buffer_guard;
+ else
+ stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
+ }
+ } else {
+ if (color_buffer)
+ funcs.glDeleteRenderbuffers(1, &color_buffer);
+ else
+ 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 QOpenGLFramebufferObject
+ \brief The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object.
+ \since 4.2
+
+ \ingroup painting-3D
+
+ The QOpenGLFramebufferObject 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 QOpenGLFramebufferObject class
+ generates a 2D GL texture (using the \c{GL_TEXTURE_2D} target),
+ which is used as the internal rendering target.
+
+ \bold{It is important to have a current GL context when creating a
+ QOpenGLFramebufferObject, otherwise initialization will fail.}
+
+ OpenGL framebuffer objects and pbuffers (see
+ \l{QOpenGLPixelBuffer}{QOpenGLPixelBuffer}) 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
+ \o 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.
+
+ \o 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.
+
+ \o 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.
+
+ \o 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 QOpenGLFramebufferObject you should take
+ care that the QOpenGLFramebufferObject is created with the CombinedDepthStencil
+ attachment for QPainter to be able to render correctly.
+ Note that you need to create a QOpenGLFramebufferObject 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 QOpenGLFramebufferObject parameter, and set the
+ QOpenGLFramebufferObject::samples() property to a non-zero value.
+
+ When painting to a QOpenGLFramebufferObject 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 QOpenGLContext::blitFramebuffer().
+
+ \section1 Threading
+
+ As of Qt 4.8, it's possible to draw into a QOpenGLFramebufferObject
+ using a QPainter in a separate thread. Note that OpenGL 2.0 or
+ OpenGL ES 2.0 is required for this to work.
+
+ \sa {Framebuffer Object Example}
+*/
+
+
+/*!
+ \enum QOpenGLFramebufferObject::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 QOpenGLFramebufferObject::QOpenGLFramebufferObject(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 QOpenGLFramebufferObject, otherwise the initialization
+ will fail.
+
+ \sa size(), texture(), attachment()
+*/
+
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ d->init(this, size, NoAttachment, target, DEFAULT_FORMAT);
+}
+
+/*! \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()
+*/
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, GLenum target)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
+}
+
+/*! \overload
+
+ Constructs an OpenGL framebuffer object of the given \a size based on the
+ supplied \a format.
+*/
+
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, const QOpenGLFramebufferObjectFormat &format)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ 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.
+*/
+
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, const QOpenGLFramebufferObjectFormat &format)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ 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()
+*/
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, Attachment attachment,
+ GLenum target, GLenum internal_format)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ 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()
+*/
+QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, Attachment attachment,
+ GLenum target, GLenum internal_format)
+ : d_ptr(new QOpenGLFramebufferObjectPrivate)
+{
+ Q_D(QOpenGLFramebufferObject);
+ d->init(this, size, attachment, target, internal_format);
+}
+
+/*!
+ \fn QOpenGLFramebufferObject::~QOpenGLFramebufferObject()
+
+ Destroys the framebuffer object and frees any allocated resources.
+*/
+QOpenGLFramebufferObject::~QOpenGLFramebufferObject()
+{
+ Q_D(QOpenGLFramebufferObject);
+
+ 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 QOpenGLFramebufferObject::isValid() const
+
+ Returns 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 QOpenGLContext that
+ the framebuffer was created within is destroyed and there are
+ no other shared contexts that can take over ownership of the
+ framebuffer.
+*/
+bool QOpenGLFramebufferObject::isValid() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ return d->valid && d->fbo_guard && d->fbo_guard->id();
+}
+
+/*!
+ \fn bool QOpenGLFramebufferObject::bind()
+
+ Switches rendering from the default, windowing system provided
+ framebuffer to this framebuffer object.
+ Returns true upon success, false otherwise.
+
+ \sa release()
+*/
+bool QOpenGLFramebufferObject::bind()
+{
+ if (!isValid())
+ return false;
+ Q_D(QOpenGLFramebufferObject);
+ QOPENGL_FUNC_CONTEXT;
+ if (!ctx)
+ return false; // Context no longer exists.
+ QOpenGLContext *current = QOpenGLContext::currentContext();
+#ifdef QT_DEBUG
+ if (!current || current->shareGroup() != d->fbo_guard->group())
+ qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
+#endif
+ d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+ d->valid = d->checkFramebufferStatus();
+ if (d->valid && current)
+ current->d_func()->current_fbo = d->fbo();
+ return d->valid;
+}
+
+/*!
+ \fn bool QOpenGLFramebufferObject::release()
+
+ Switches rendering back to the default, windowing system provided
+ framebuffer.
+ Returns true upon success, false otherwise.
+
+ \sa bind()
+*/
+bool QOpenGLFramebufferObject::release()
+{
+ if (!isValid())
+ return false;
+ QOPENGL_FUNC_CONTEXT;
+ if (!ctx)
+ return false; // Context no longer exists.
+
+ QOpenGLContext *current = QOpenGLContext::currentContext();
+
+#ifdef QT_DEBUG
+ Q_D(QOpenGLFramebufferObject);
+ if (!current || current->shareGroup() != d->fbo_guard->group())
+ qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
+#endif
+
+ if (current) {
+ current->d_func()->current_fbo = current->d_func()->default_fbo;
+ d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->default_fbo);
+ }
+
+ return true;
+}
+
+/*!
+ \fn GLuint QOpenGLFramebufferObject::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 QOpenGLFramebufferObject::texture() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ return d->texture_guard ? d->texture_guard->id() : 0;
+}
+
+/*!
+ \fn QSize QOpenGLFramebufferObject::size() const
+
+ Returns the size of the texture attached to this framebuffer
+ object.
+*/
+QSize QOpenGLFramebufferObject::size() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ return d->size;
+}
+
+/*!
+ Returns the format of this framebuffer object.
+*/
+QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ return d->format;
+}
+
+namespace {
+/*
+ Read back the contents of the currently bound framebuffer, used in
+ QGLWidget::grabFrameBuffer(), QGLPixelbuffer::toImage() and
+ QGLFramebufferObject::toImage()
+*/
+
+void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
+{
+ 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();
+}
+
+}
+
+Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
+{
+ QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_RGB32);
+ int w = size.width();
+ int h = size.height();
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+ convertFromGLImage(img, w, h, alpha_format, include_alpha);
+ return img;
+}
+
+/*!
+ \fn QImage QOpenGLFramebufferObject::toImage() const
+
+ Returns the contents of this framebuffer object as a QImage.
+*/
+QImage QOpenGLFramebufferObject::toImage() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ if (!d->valid)
+ return QImage();
+
+ // qt_gl_read_framebuffer doesn't work on a multisample FBO
+ if (format().samples() != 0) {
+ QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat());
+
+ QRect rect(QPoint(0, 0), size());
+ blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);
+
+ return temp.toImage();
+ }
+
+ bool wasBound = isBound();
+ if (!wasBound)
+ const_cast<QOpenGLFramebufferObject *>(this)->bind();
+ QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != GL_RGB, true);
+ if (!wasBound)
+ const_cast<QOpenGLFramebufferObject *>(this)->release();
+
+ return image;
+}
+
+Q_GLOBAL_STATIC(QOpenGLEngineThreadStorage<QOpenGL2PaintEngineEx>, qt_buffer_2_engine)
+
+/*! \reimp */
+QPaintEngine *QOpenGLFramebufferObject::paintEngine() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ if (d->engine)
+ return d->engine;
+
+ QPaintEngine *engine = qt_buffer_2_engine()->engine();
+ if (engine->isActive() && engine->paintDevice() != this) {
+ d->engine = new QOpenGL2PaintEngineEx;
+ return d->engine;
+ }
+ return engine;
+}
+
+/*!
+ \fn bool QOpenGLFramebufferObject::bindDefault()
+ \internal
+
+ Switches rendering back to the default, windowing system provided
+ framebuffer.
+ Returns true upon success, false otherwise.
+
+ \sa bind(), release()
+*/
+bool QOpenGLFramebufferObject::bindDefault()
+{
+ QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ QOpenGLFunctions functions(ctx);
+
+ if (ctx) {
+ ctx->d_func()->current_fbo = ctx->d_func()->default_fbo;
+ functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->default_fbo);
+#ifdef QT_DEBUG
+ } else {
+ qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
+#endif
+ }
+
+ return ctx != 0;
+}
+
+/*!
+ \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()
+
+ Returns true if the OpenGL \c{GL_EXT_framebuffer_object} extension
+ is present on this system; otherwise returns false.
+*/
+bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()
+{
+ return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
+}
+
+/*! \reimp */
+int QOpenGLFramebufferObject::metric(PaintDeviceMetric metric) const
+{
+ Q_D(const QOpenGLFramebufferObject);
+
+ 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);
+
+ default:
+ qWarning("QOpenGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
+ break;
+ }
+ return 0;
+}
+
+/*!
+ \fn GLuint QOpenGLFramebufferObject::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 QOpenGLFramebufferObject::handle() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ return d->fbo();
+}
+
+/*! \fn int QOpenGLFramebufferObject::devType() const
+ \internal
+*/
+
+
+/*!
+ Returns the status of the depth and stencil buffers attached to
+ this framebuffer object.
+*/
+
+QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObject::attachment() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ if (d->valid)
+ return d->fbo_attachment;
+ return NoAttachment;
+}
+
+/*!
+ \since 4.5
+
+ Returns true if the framebuffer object is currently bound to a context,
+ otherwise false is returned.
+*/
+
+bool QOpenGLFramebufferObject::isBound() const
+{
+ Q_D(const QOpenGLFramebufferObject);
+ QOpenGLContext *current = QOpenGLContext::currentContext();
+ return current ? current->d_func()->current_fbo == d->fbo() : false;
+}
+
+/*!
+ \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()
+
+ \since 4.6
+
+ Returns true if the OpenGL \c{GL_EXT_framebuffer_blit} extension
+ is present on this system; otherwise returns false.
+
+ \sa blitFramebuffer()
+*/
+bool QOpenGLFramebufferObject::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 0, 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 QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect,
+ QOpenGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers,
+ GLenum filter)
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx)
+ return;
+
+ QOpenGLExtensions extensions(ctx);
+ if (!extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
+ return;
+
+ QSurface *surface = ctx->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();
+
+ extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
+ extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
+
+ extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
+ tx0, ty0, tx1, ty1,
+ buffers, filter);
+
+ extensions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglframebufferobject.h b/src/gui/opengl/qopenglframebufferobject.h
new file mode 100644
index 0000000000..d1bd09c629
--- /dev/null
+++ b/src/gui/opengl/qopenglframebufferobject.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLFRAMEBUFFEROBJECT_H
+#define QOPENGLFRAMEBUFFEROBJECT_H
+
+#include <QtGui/qopengl.h>
+#include <QtGui/qpaintdevice.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QOpenGLFramebufferObjectPrivate;
+class QOpenGLFramebufferObjectFormat;
+
+class Q_GUI_EXPORT QOpenGLFramebufferObject : public QPaintDevice
+{
+ Q_DECLARE_PRIVATE(QOpenGLFramebufferObject)
+public:
+ enum Attachment {
+ NoAttachment,
+ CombinedDepthStencil,
+ Depth
+ };
+
+ QOpenGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D);
+ QOpenGLFramebufferObject(int width, int height, GLenum target = GL_TEXTURE_2D);
+#if !defined(QT_OPENGL_ES) || defined(Q_QDOC)
+ QOpenGLFramebufferObject(const QSize &size, Attachment attachment,
+ GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8);
+ QOpenGLFramebufferObject(int width, int height, Attachment attachment,
+ GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8);
+#else
+ QOpenGLFramebufferObject(const QSize &size, Attachment attachment,
+ GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
+ QOpenGLFramebufferObject(int width, int height, Attachment attachment,
+ GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
+#endif
+
+ QOpenGLFramebufferObject(const QSize &size, const QOpenGLFramebufferObjectFormat &format);
+ QOpenGLFramebufferObject(int width, int height, const QOpenGLFramebufferObjectFormat &format);
+
+ virtual ~QOpenGLFramebufferObject();
+
+ QOpenGLFramebufferObjectFormat 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;
+ GLuint handle() const;
+
+ static bool bindDefault();
+
+ static bool hasOpenGLFramebufferObjects();
+
+ static bool hasOpenGLFramebufferBlit();
+ static void blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect,
+ QOpenGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers = GL_COLOR_BUFFER_BIT,
+ GLenum filter = GL_NEAREST);
+
+protected:
+ int metric(PaintDeviceMetric metric) const;
+ int devType() const { return QInternal::FramebufferObject; }
+
+private:
+ Q_DISABLE_COPY(QOpenGLFramebufferObject)
+ QScopedPointer<QOpenGLFramebufferObjectPrivate> d_ptr;
+ friend class QOpenGLPaintDevice;
+ friend class QOpenGLFBOGLPaintDevice;
+};
+
+class QOpenGLFramebufferObjectFormatPrivate;
+class Q_GUI_EXPORT QOpenGLFramebufferObjectFormat
+{
+public:
+ QOpenGLFramebufferObjectFormat();
+ QOpenGLFramebufferObjectFormat(const QOpenGLFramebufferObjectFormat &other);
+ QOpenGLFramebufferObjectFormat &operator=(const QOpenGLFramebufferObjectFormat &other);
+ ~QOpenGLFramebufferObjectFormat();
+
+ void setSamples(int samples);
+ int samples() const;
+
+ void setMipmap(bool enabled);
+ bool mipmap() const;
+
+ void setAttachment(QOpenGLFramebufferObject::Attachment attachment);
+ QOpenGLFramebufferObject::Attachment attachment() const;
+
+ void setTextureTarget(GLenum target);
+ GLenum textureTarget() const;
+
+ void setInternalTextureFormat(GLenum internalTextureFormat);
+ GLenum internalTextureFormat() const;
+
+ bool operator==(const QOpenGLFramebufferObjectFormat& other) const;
+ bool operator!=(const QOpenGLFramebufferObjectFormat& other) const;
+
+private:
+ QOpenGLFramebufferObjectFormatPrivate *d;
+
+ void detach();
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+#endif // QOPENGLFRAMEBUFFEROBJECT_H
diff --git a/src/gui/opengl/qopenglframebufferobject_p.h b/src/gui/opengl/qopenglframebufferobject_p.h
new file mode 100644
index 0000000000..6ea6eb26ee
--- /dev/null
+++ b/src/gui/opengl/qopenglframebufferobject_p.h
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLFRAMEBUFFEROBJECT_P_H
+#define QOPENGLFRAMEBUFFEROBJECT_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 QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+#include <qopenglframebufferobject.h>
+#include <private/qopenglpaintdevice_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglextensions_p.h>
+
+QT_END_INCLUDE_NAMESPACE
+
+#ifndef QT_OPENGL_ES
+#define DEFAULT_FORMAT GL_RGBA8
+#else
+#define DEFAULT_FORMAT GL_RGBA
+#endif
+
+class QOpenGLFramebufferObjectFormatPrivate
+{
+public:
+ QOpenGLFramebufferObjectFormatPrivate()
+ : ref(1),
+ samples(0),
+ attachment(QOpenGLFramebufferObject::NoAttachment),
+ target(GL_TEXTURE_2D),
+ internal_format(DEFAULT_FORMAT),
+ mipmap(false)
+ {
+ }
+ QOpenGLFramebufferObjectFormatPrivate
+ (const QOpenGLFramebufferObjectFormatPrivate *other)
+ : ref(1),
+ samples(other->samples),
+ attachment(other->attachment),
+ target(other->target),
+ internal_format(other->internal_format),
+ mipmap(other->mipmap)
+ {
+ }
+ bool equals(const QOpenGLFramebufferObjectFormatPrivate *other)
+ {
+ return samples == other->samples &&
+ attachment == other->attachment &&
+ target == other->target &&
+ internal_format == other->internal_format &&
+ mipmap == other->mipmap;
+ }
+
+ QAtomicInt ref;
+ int samples;
+ QOpenGLFramebufferObject::Attachment attachment;
+ GLenum target;
+ GLenum internal_format;
+ uint mipmap : 1;
+};
+
+class QOpenGLFBOGLPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ virtual QPaintEngine* paintEngine() const {return fbo->paintEngine();}
+ virtual QSize size() const {return fbo->size();}
+ virtual QSurfaceFormat format() const {return fboFormat;}
+ virtual QOpenGLContextGroup *group() const;
+ virtual bool alphaRequested() const { return reqAlpha; }
+
+ void setFBO(QOpenGLFramebufferObject* f,
+ QOpenGLFramebufferObject::Attachment attachment);
+
+private:
+ QOpenGLFramebufferObject* fbo;
+ QSurfaceFormat fboFormat;
+ bool wasBound;
+ bool reqAlpha;
+};
+
+class QOpenGLFramebufferObjectPrivate
+{
+public:
+ QOpenGLFramebufferObjectPrivate() : fbo_guard(0), texture_guard(0), depth_buffer_guard(0)
+ , stencil_buffer_guard(0), color_buffer_guard(0)
+ , valid(false), engine(0) {}
+ ~QOpenGLFramebufferObjectPrivate() {}
+
+ void init(QOpenGLFramebufferObject *q, const QSize& sz,
+ QOpenGLFramebufferObject::Attachment attachment,
+ GLenum internal_format, GLenum texture_target,
+ GLint samples = 0, bool mipmap = false);
+ bool checkFramebufferStatus() const;
+ QOpenGLSharedResourceGuard *fbo_guard;
+ QOpenGLSharedResourceGuard *texture_guard;
+ QOpenGLSharedResourceGuard *depth_buffer_guard;
+ QOpenGLSharedResourceGuard *stencil_buffer_guard;
+ QOpenGLSharedResourceGuard *color_buffer_guard;
+ GLenum target;
+ QSize size;
+ QOpenGLFramebufferObjectFormat format;
+ uint valid : 1;
+ QOpenGLFramebufferObject::Attachment fbo_attachment;
+ mutable QPaintEngine *engine;
+ QOpenGLFBOGLPaintDevice glDevice;
+ QOpenGLExtensions funcs;
+
+ inline GLuint fbo() const { return fbo_guard ? fbo_guard->id() : 0; }
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QOPENGLFRAMEBUFFEROBJECT_P_H
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
new file mode 100644
index 0000000000..4ef80bfa89
--- /dev/null
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -0,0 +1,2452 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglfunctions.h"
+#include "qopenglextensions_p.h"
+#include "qdebug.h"
+#include "QtGui/private/qopenglcontext_p.h"
+#include "QtGui/private/qopengl_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLFunctions
+ \brief The QOpenGLFunctions class provides cross-platform access to the OpenGL/ES 2.0 API.
+ \since 4.8
+ \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.
+
+ QOpenGLFunctions 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 QOpenGLFunctions is by
+ direct inheritance:
+
+ \code
+ class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
+ {
+ Q_OBJECT
+ public:
+ MyGLWidget(QWidget *parent = 0) : QOpenGLWidget(parent) {}
+
+ protected:
+ void initializeGL();
+ void paintGL();
+ };
+
+ void MyGLWidget::initializeGL()
+ {
+ initializeGLFunctions();
+ }
+ \endcode
+
+ 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:
+
+ \code
+ void MyGLWidget::paintGL()
+ {
+ glActiveTexture(GL_TEXTURE1);
+ glBindTexture(GL_TEXTURE_2D, textureId);
+ ...
+ }
+ \endcode
+
+ QOpenGLFunctions can also be used directly for ad-hoc invocation
+ of OpenGL/ES 2.0 functions on all platforms:
+
+ \code
+ QOpenGLFunctions glFuncs(QOpenGLContext::currentContext());
+ glFuncs.glActiveTexture(GL_TEXTURE1);
+ \endcode
+
+ QOpenGLFunctions 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 QOpenGLFunctions 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:
+
+ \code
+ QOpenGLFunctions funcs(QOpenGLContext::currentContext());
+ bool npot = funcs.hasOpenGLFeature(QOpenGLFunctions::NPOTTextures);
+ \endcode
+*/
+
+/*!
+ \enum QOpenGLFunctions::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 QOpenGLFunctionsPrivateEx : public QOpenGLExtensionsPrivate, public QOpenGLSharedResource
+{
+ QOpenGLFunctionsPrivateEx(QOpenGLContext *context)
+ : QOpenGLExtensionsPrivate(context)
+ , QOpenGLSharedResource(context->shareGroup())
+ , m_features(-1)
+ , m_extensions(-1)
+ {}
+
+ void invalidateResource()
+ {
+ m_features = -1;
+ m_extensions = -1;
+ }
+
+ void freeResource(QOpenGLContext *)
+ {
+ // no gl resources to free
+ }
+
+ int m_features;
+ int m_extensions;
+};
+
+Q_GLOBAL_STATIC(QOpenGLMultiGroupSharedResource, qt_gl_functions_resource)
+
+static QOpenGLFunctionsPrivateEx *qt_gl_functions(QOpenGLContext *context = 0)
+{
+ if (!context)
+ context = QOpenGLContext::currentContext();
+ Q_ASSERT(context);
+ QOpenGLFunctionsPrivateEx *funcs =
+ qt_gl_functions_resource()->value<QOpenGLFunctionsPrivateEx>(context);
+ return funcs;
+}
+
+/*!
+ Constructs a default function resolver. The resolver cannot
+ be used until initializeGLFunctions() is called to specify
+ the context.
+
+ \sa initializeGLFunctions()
+*/
+QOpenGLFunctions::QOpenGLFunctions()
+ : d_ptr(0)
+{
+}
+
+/*!
+ Constructs a function resolver for \a context. If \a context
+ is null, then the resolver will be created for the current QOpenGLContext.
+
+ The context or another context in the group must be current.
+
+ 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()
+*/
+QOpenGLFunctions::QOpenGLFunctions(QOpenGLContext *context)
+ : d_ptr(0)
+{
+ if (context && QOpenGLContextGroup::currentContextGroup() == context->shareGroup())
+ d_ptr = qt_gl_functions();
+ else
+ qWarning() << "QOpenGLFunctions created with non-current context";
+}
+
+QOpenGLExtensions::QOpenGLExtensions()
+ : QOpenGLFunctions()
+{
+}
+
+QOpenGLExtensions::QOpenGLExtensions(QOpenGLContext *context)
+ : QOpenGLFunctions(context)
+{
+}
+
+/*!
+ \fn QOpenGLFunctions::~QOpenGLFunctions()
+
+ Destroys this function resolver.
+*/
+
+static int qt_gl_resolve_features()
+{
+#if defined(QT_OPENGL_ES_2)
+ int features = QOpenGLFunctions::Multitexture |
+ QOpenGLFunctions::Shaders |
+ QOpenGLFunctions::Buffers |
+ QOpenGLFunctions::Framebuffers |
+ QOpenGLFunctions::BlendColor |
+ QOpenGLFunctions::BlendEquation |
+ QOpenGLFunctions::BlendEquationSeparate |
+ QOpenGLFunctions::BlendFuncSeparate |
+ QOpenGLFunctions::BlendSubtract |
+ QOpenGLFunctions::CompressedTextures |
+ QOpenGLFunctions::Multisample |
+ QOpenGLFunctions::StencilSeparate;
+ QOpenGLExtensionMatcher extensions;
+ if (extensions.match("GL_OES_texture_npot"))
+ features |= QOpenGLFunctions::NPOTTextures;
+ if (extensions.match("GL_IMG_texture_npot"))
+ features |= QOpenGLFunctions::NPOTTextures;
+ return features;
+#elif defined(QT_OPENGL_ES)
+ int features = QOpenGLFunctions::Multitexture |
+ QOpenGLFunctions::Buffers |
+ QOpenGLFunctions::CompressedTextures |
+ QOpenGLFunctions::Multisample;
+ QOpenGLExtensionMatcher extensions;
+ if (extensions.match("GL_OES_framebuffer_object"))
+ features |= QOpenGLFunctions::Framebuffers;
+ if (extensions.match("GL_OES_blend_equation_separate"))
+ features |= QOpenGLFunctions::BlendEquationSeparate;
+ if (extensions.match("GL_OES_blend_func_separate"))
+ features |= QOpenGLFunctions::BlendFuncSeparate;
+ if (extensions.match("GL_OES_blend_subtract"))
+ features |= QOpenGLFunctions::BlendSubtract;
+ if (extensions.match("GL_OES_texture_npot"))
+ features |= QOpenGLFunctions::NPOTTextures;
+ if (extensions.match("GL_IMG_texture_npot"))
+ features |= QOpenGLFunctions::NPOTTextures;
+ return features;
+#else
+ int features = 0;
+ //QOpenGLFormat::OpenGLVersionFlags versions = QOpenGLFormat::openGLVersionFlags();
+ QOpenGLExtensionMatcher extensions;
+
+ // Recognize features by extension name.
+ if (extensions.match("GL_ARB_multitexture"))
+ features |= QOpenGLFunctions::Multitexture;
+ if (extensions.match("GL_ARB_shader_objects"))
+ features |= QOpenGLFunctions::Shaders;
+ if (extensions.match("GL_EXT_framebuffer_object") ||
+ extensions.match("GL_ARB_framebuffer_object"))
+ features |= QOpenGLFunctions::Framebuffers;
+ if (extensions.match("GL_EXT_blend_color"))
+ features |= QOpenGLFunctions::BlendColor;
+ if (extensions.match("GL_EXT_blend_equation_separate"))
+ features |= QOpenGLFunctions::BlendEquationSeparate;
+ if (extensions.match("GL_EXT_blend_func_separate"))
+ features |= QOpenGLFunctions::BlendFuncSeparate;
+ if (extensions.match("GL_EXT_blend_subtract"))
+ features |= QOpenGLFunctions::BlendSubtract;
+ if (extensions.match("GL_ARB_texture_compression"))
+ features |= QOpenGLFunctions::CompressedTextures;
+ if (extensions.match("GL_ARB_multisample"))
+ features |= QOpenGLFunctions::Multisample;
+ if (extensions.match("GL_ARB_texture_non_power_of_two"))
+ features |= QOpenGLFunctions::NPOTTextures;
+
+ // assume version 2.0 or higher
+ features |= QOpenGLFunctions::BlendColor |
+ QOpenGLFunctions::BlendEquation |
+ QOpenGLFunctions::Multitexture |
+ QOpenGLFunctions::CompressedTextures |
+ QOpenGLFunctions::Multisample |
+ QOpenGLFunctions::BlendFuncSeparate |
+ QOpenGLFunctions::Buffers |
+ QOpenGLFunctions::Shaders |
+ QOpenGLFunctions::StencilSeparate |
+ QOpenGLFunctions::BlendEquationSeparate |
+ QOpenGLFunctions::NPOTTextures;
+ return features;
+#endif
+}
+
+static int qt_gl_resolve_extensions()
+{
+ int extensions = 0;
+ QOpenGLExtensionMatcher extensionMatcher;
+#if defined(QT_OPENGL_ES)
+ if (extensionMatcher.match("GL_OES_mapbuffer"))
+ extensions |= QOpenGLExtensions::MapBuffer;
+ if (extensionMatcher.match("GL_OES_packed_depth_stencil"))
+ extensions |= QOpenGLExtensions::PackedDepthStencil;
+ if (extensionMatcher.match("GL_OES_element_index_uint"))
+ extensions |= QOpenGLExtensions::ElementIndexUint;
+ if (extensionMatcher.match("GL_OES_depth24"))
+ extensions |= QOpenGLExtensions::Depth24;
+#else
+ extensions |= QOpenGLExtensions::ElementIndexUint | QOpenGLExtensions::MapBuffer;
+
+ // Recognize features by extension name.
+ if (extensionMatcher.match("GL_ARB_framebuffer_object")) {
+ extensions |= QOpenGLExtensions::FramebufferMultisample |
+ QOpenGLExtensions::FramebufferBlit |
+ QOpenGLExtensions::PackedDepthStencil;
+ } else {
+ if (extensionMatcher.match("GL_EXT_framebuffer_multisample"))
+ extensions |= QOpenGLExtensions::FramebufferMultisample;
+ if (extensionMatcher.match("GL_EXT_framebuffer_blit"))
+ extensions |= QOpenGLExtensions::FramebufferBlit;
+ if (extensionMatcher.match("GL_EXT_pakced_depth_stencil"))
+ extensions |= QOpenGLExtensions::PackedDepthStencil;
+ }
+#endif
+ return extensions;
+}
+
+/*!
+ Returns the set of features that are present on this system's
+ OpenGL implementation.
+
+ It is assumed that the QOpenGLContext associated with this function
+ resolver is current.
+
+ \sa hasOpenGLFeature()
+*/
+QOpenGLFunctions::OpenGLFeatures QOpenGLFunctions::openGLFeatures() const
+{
+ QOpenGLFunctionsPrivateEx *d = static_cast<QOpenGLFunctionsPrivateEx *>(d_ptr);
+ if (!d)
+ return 0;
+ if (d->m_features == -1)
+ d->m_features = qt_gl_resolve_features();
+ return QOpenGLFunctions::OpenGLFeatures(d->m_features);
+}
+
+/*!
+ Returns true if \a feature is present on this system's OpenGL
+ implementation; false otherwise.
+
+ It is assumed that the QOpenGLContext associated with this function
+ resolver is current.
+
+ \sa openGLFeatures()
+*/
+bool QOpenGLFunctions::hasOpenGLFeature(QOpenGLFunctions::OpenGLFeature feature) const
+{
+ QOpenGLFunctionsPrivateEx *d = static_cast<QOpenGLFunctionsPrivateEx *>(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;
+}
+
+/*!
+ Returns the set of extensions that are present on this system's
+ OpenGL implementation.
+
+ It is assumed that the QOpenGLContext associated with this extension
+ resolver is current.
+
+ \sa hasOpenGLExtensions()
+*/
+QOpenGLExtensions::OpenGLExtensions QOpenGLExtensions::openGLExtensions()
+{
+ QOpenGLFunctionsPrivateEx *d = static_cast<QOpenGLFunctionsPrivateEx *>(d_ptr);
+ if (!d)
+ return 0;
+ if (d->m_extensions == -1)
+ d->m_extensions = qt_gl_resolve_extensions();
+ return QOpenGLExtensions::OpenGLExtensions(d->m_extensions);
+}
+
+/*!
+ Returns true if \a extension is present on this system's OpenGL
+ implementation; false otherwise.
+
+ It is assumed that the QOpenGLContext associated with this extension
+ resolver is current.
+
+ \sa openGLFeatures()
+*/
+bool QOpenGLExtensions::hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const
+{
+ QOpenGLFunctionsPrivateEx *d = static_cast<QOpenGLFunctionsPrivateEx *>(d_ptr);
+ if (!d)
+ return false;
+ if (d->m_extensions == -1)
+ d->m_extensions = qt_gl_resolve_extensions();
+ return (d->m_extensions & int(extension)) != 0;
+}
+
+/*!
+ Initializes GL function resolution for the current context.
+
+ After calling this function, the QOpenGLFunctions object can only be
+ used with the current context and other contexts that share with it.
+ Call initializeGLFunctions() again to change the object's context
+ association.
+*/
+void QOpenGLFunctions::initializeGLFunctions()
+{
+ d_ptr = qt_gl_functions();
+}
+
+/*!
+ \fn void QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
+
+ Convenience function that calls glBindFramebuffer(\a target, \a framebuffer).
+
+ 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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 GLint QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 GLint QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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 QOpenGLFunctions::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.
+*/
+
+namespace {
+
+enum ResolvePolicy
+{
+ ResolveOES = 0x1,
+ ResolveEXT = 0x2
+};
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType>
+class Resolver
+{
+public:
+ Resolver(FuncType Base::*func, FuncType fallback, const char *name, const char *alternateName = 0)
+ : funcPointerName(func)
+ , fallbackFuncPointer(fallback)
+ , funcName(name)
+ , alternateFuncName(alternateName)
+ {
+ }
+
+ ReturnType operator()();
+
+ template <typename P1>
+ ReturnType operator()(P1 p1);
+
+ template <typename P1, typename P2>
+ ReturnType operator()(P1 p1, P2 p2);
+
+ template <typename P1, typename P2, typename P3>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3);
+
+ template <typename P1, typename P2, typename P3, typename P4>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
+ ReturnType operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10);
+
+private:
+ FuncType Base::*funcPointerName;
+ FuncType fallbackFuncPointer;
+ QByteArray funcName;
+ QByteArray alternateFuncName;
+};
+
+template <typename Base, typename FuncType, int Policy>
+class Resolver<Base, FuncType, Policy, void>
+{
+public:
+ Resolver(FuncType Base::*func, FuncType fallback, const char *name, const char *alternateName = 0)
+ : funcPointerName(func)
+ , fallbackFuncPointer(fallback)
+ , funcName(name)
+ , alternateFuncName(alternateName)
+ {
+ }
+
+ void operator()();
+
+ template <typename P1>
+ void operator()(P1 p1);
+
+ template <typename P1, typename P2>
+ void operator()(P1 p1, P2 p2);
+
+ template <typename P1, typename P2, typename P3>
+ void operator()(P1 p1, P2 p2, P3 p3);
+
+ template <typename P1, typename P2, typename P3, typename P4>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9);
+
+ template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
+ void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10);
+
+private:
+ FuncType Base::*funcPointerName;
+ FuncType fallbackFuncPointer;
+ QByteArray funcName;
+ QByteArray alternateFuncName;
+};
+
+#define RESOLVER_COMMON \
+ QOpenGLContext *context = QOpenGLContext::currentContext(); \
+ Base *funcs = qt_gl_functions(context); \
+ \
+ FuncType old = funcs->*funcPointerName; \
+ \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName); \
+ \
+ if ((Policy & ResolveOES) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "OES"); \
+ \
+ if (!(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "ARB"); \
+ \
+ if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(funcName + "EXT"); \
+ \
+ if (!alternateFuncName.isEmpty() && !(funcs->*funcPointerName)) { \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName); \
+ \
+ if ((Policy & ResolveOES) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "OES"); \
+ \
+ if (!(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "ARB"); \
+ \
+ if ((Policy & ResolveEXT) && !(funcs->*funcPointerName)) \
+ funcs->*funcPointerName = (FuncType)context->getProcAddress(alternateFuncName + "EXT"); \
+ }
+
+#define RESOLVER_COMMON_NON_VOID \
+ RESOLVER_COMMON \
+ \
+ if (!(funcs->*funcPointerName)) { \
+ if (fallbackFuncPointer) { \
+ funcs->*funcPointerName = fallbackFuncPointer; \
+ } else { \
+ funcs->*funcPointerName = old; \
+ return ReturnType(); \
+ } \
+ }
+
+#define RESOLVER_COMMON_VOID \
+ RESOLVER_COMMON \
+ \
+ if (!(funcs->*funcPointerName)) { \
+ if (fallbackFuncPointer) { \
+ funcs->*funcPointerName = fallbackFuncPointer; \
+ } else { \
+ funcs->*funcPointerName = old; \
+ return; \
+ } \
+ }
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()()
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)();
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+template <typename Base, typename FuncType, int Policy, typename ReturnType> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
+ReturnType Resolver<Base, FuncType, Policy, ReturnType>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10)
+{
+ RESOLVER_COMMON_NON_VOID
+
+ return (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+}
+
+template <typename Base, typename FuncType, int Policy>
+void Resolver<Base, FuncType, Policy, void>::operator()()
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)();
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8, p9);
+}
+
+template <typename Base, typename FuncType, int Policy> template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8, typename P9, typename P10>
+void Resolver<Base, FuncType, Policy, void>::operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9, P10 p10)
+{
+ RESOLVER_COMMON_VOID
+
+ (funcs->*funcPointerName)(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
+}
+
+template <typename ReturnType, int Policy, typename Base, typename FuncType>
+Resolver<Base, FuncType, Policy, ReturnType> functionResolverWithFallback(FuncType Base::*func, FuncType fallback, const char *name, const char *alternate = 0)
+{
+ return Resolver<Base, FuncType, Policy, ReturnType>(func, fallback, name, alternate);
+}
+
+template <typename ReturnType, int Policy, typename Base, typename FuncType>
+Resolver<Base, FuncType, Policy, ReturnType> functionResolver(FuncType Base::*func, const char *name, const char *alternate = 0)
+{
+ return Resolver<Base, FuncType, Policy, ReturnType>(func, 0, name, alternate);
+}
+
+}
+
+#define RESOLVE_FUNC(RETURN_TYPE, POLICY, NAME) \
+ return functionResolver<RETURN_TYPE, POLICY>(&QOpenGLExtensionsPrivate::NAME, "gl" #NAME)
+
+#define RESOLVE_FUNC_VOID(POLICY, NAME) \
+ functionResolver<void, POLICY>(&QOpenGLExtensionsPrivate::NAME, "gl" #NAME)
+
+#define RESOLVE_FUNC_SPECIAL(RETURN_TYPE, POLICY, NAME) \
+ return functionResolverWithFallback<RETURN_TYPE, POLICY>(&QOpenGLExtensionsPrivate::NAME, qopenglfSpecial##NAME, "gl" #NAME)
+
+#define RESOLVE_FUNC_SPECIAL_VOID(POLICY, NAME) \
+ functionResolverWithFallback<void, POLICY>(&QOpenGLExtensionsPrivate::NAME, qopenglfSpecial##NAME, "gl" #NAME)
+
+#define RESOLVE_FUNC_WITH_ALTERNATE(RETURN_TYPE, POLICY, NAME, ALTERNATE) \
+ return functionResolver<RETURN_TYPE, POLICY>(&QOpenGLExtensionsPrivate::NAME, "gl" #NAME, "gl" #ALTERNATE)
+
+#define RESOLVE_FUNC_VOID_WITH_ALTERNATE(POLICY, NAME, ALTERNATE) \
+ functionResolver<void, POLICY>(&QOpenGLExtensionsPrivate::NAME, "gl" #NAME, "gl" #ALTERNATE)
+
+#ifndef QT_OPENGL_ES_2
+
+static void QOPENGLF_APIENTRY qopenglfResolveActiveTexture(GLenum texture)
+{
+ RESOLVE_FUNC_VOID(0, ActiveTexture)(texture);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveAttachShader(GLuint program, GLuint shader)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, AttachShader, AttachObject)(program, shader);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBindAttribLocation(GLuint program, GLuint index, const char* name)
+{
+ RESOLVE_FUNC_VOID(0, BindAttribLocation)(program, index, name);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBindBuffer(GLenum target, GLuint buffer)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BindBuffer)(target, buffer);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BindFramebuffer)(target, framebuffer);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BindRenderbuffer)(target, renderbuffer);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BlendColor)(red, green, blue, alpha);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBlendEquation(GLenum mode)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BlendEquation)(mode);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BlendEquationSeparate)(modeRGB, modeAlpha);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BlendFuncSeparate)(srcRGB, dstRGB, srcAlpha, dstAlpha);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BufferData)(target, size, data, usage);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, BufferSubData)(target, offset, size, data);
+}
+
+static GLenum QOPENGLF_APIENTRY qopenglfResolveCheckFramebufferStatus(GLenum target)
+{
+ RESOLVE_FUNC(GLenum, ResolveOES | ResolveEXT, CheckFramebufferStatus)(target);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveCompileShader(GLuint shader)
+{
+ RESOLVE_FUNC_VOID(0, CompileShader)(shader);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, CompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, CompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+}
+
+static GLuint QOPENGLF_APIENTRY qopenglfResolveCreateProgram()
+{
+ RESOLVE_FUNC_WITH_ALTERNATE(GLuint, 0, CreateProgram, CreateProgramObject)();
+}
+
+static GLuint QOPENGLF_APIENTRY qopenglfResolveCreateShader(GLenum type)
+{
+ RESOLVE_FUNC_WITH_ALTERNATE(GLuint, 0, CreateShader, CreateShaderObject)(type);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, DeleteBuffers)(n, buffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, DeleteFramebuffers)(n, framebuffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDeleteProgram(GLuint program)
+{
+ RESOLVE_FUNC_VOID(0, DeleteProgram)(program);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, DeleteRenderbuffers)(n, renderbuffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDeleteShader(GLuint shader)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, DeleteShader, DeleteObject)(shader);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDetachShader(GLuint program, GLuint shader)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, DetachShader, DetachObject)(program, shader);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveDisableVertexAttribArray(GLuint index)
+{
+ RESOLVE_FUNC_VOID(0, DisableVertexAttribArray)(index);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveEnableVertexAttribArray(GLuint index)
+{
+ RESOLVE_FUNC_VOID(0, EnableVertexAttribArray)(index);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, FramebufferRenderbuffer)(target, attachment, renderbuffertarget, renderbuffer);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, FramebufferTexture2D)(target, attachment, textarget, texture, level);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGenBuffers(GLsizei n, GLuint* buffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GenBuffers)(n, buffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGenerateMipmap(GLenum target)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GenerateMipmap)(target);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GenFramebuffers)(n, framebuffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GenRenderbuffers)(n, renderbuffers);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+{
+ RESOLVE_FUNC_VOID(0, GetActiveAttrib)(program, index, bufsize, length, size, type, name);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+{
+ RESOLVE_FUNC_VOID(0, GetActiveUniform)(program, index, bufsize, length, size, type, name);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, GetAttachedShaders, GetAttachedObjects)(program, maxcount, count, shaders);
+}
+
+static GLint QOPENGLF_APIENTRY qopenglfResolveGetAttribLocation(GLuint program, const char* name)
+{
+ RESOLVE_FUNC(GLint, 0, GetAttribLocation)(program, name);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GetBufferParameteriv)(target, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GetFramebufferAttachmentParameteriv)(target, attachment, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, GetProgramiv, GetObjectParameteriv)(program, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, GetProgramInfoLog, GetInfoLog)(program, bufsize, length, infolog);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, GetRenderbufferParameteriv)(target, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, GetShaderiv, GetObjectParameteriv)(shader, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+ RESOLVE_FUNC_VOID_WITH_ALTERNATE(0, GetShaderInfoLog, GetInfoLog)(shader, bufsize, length, infolog);
+}
+
+static void QOPENGLF_APIENTRY qopenglfSpecialGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+ Q_UNUSED(shadertype);
+ Q_UNUSED(precisiontype);
+ range[0] = range[1] = precision[0] = 0;
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+ RESOLVE_FUNC_SPECIAL_VOID(ResolveOES | ResolveEXT, GetShaderPrecisionFormat)(shadertype, precisiontype, range, precision);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+{
+ RESOLVE_FUNC_VOID(0, GetShaderSource)(shader, bufsize, length, source);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+ RESOLVE_FUNC_VOID(0, GetUniformfv)(program, location, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+ RESOLVE_FUNC_VOID(0, GetUniformiv)(program, location, params);
+}
+
+static GLint QOPENGLF_APIENTRY qopenglfResolveGetUniformLocation(GLuint program, const char* name)
+{
+ RESOLVE_FUNC(GLint, 0, GetUniformLocation)(program, name);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+ RESOLVE_FUNC_VOID(0, GetVertexAttribfv)(index, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+ RESOLVE_FUNC_VOID(0, GetVertexAttribiv)(index, pname, params);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
+{
+ RESOLVE_FUNC_VOID(0, GetVertexAttribPointerv)(index, pname, pointer);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveIsBuffer(GLuint buffer)
+{
+ RESOLVE_FUNC(GLboolean, ResolveOES | ResolveEXT, IsBuffer)(buffer);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveIsFramebuffer(GLuint framebuffer)
+{
+ RESOLVE_FUNC(GLboolean, ResolveOES | ResolveEXT, IsFramebuffer)(framebuffer);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfSpecialIsProgram(GLuint program)
+{
+ return program != 0;
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveIsProgram(GLuint program)
+{
+ RESOLVE_FUNC_SPECIAL(GLboolean, 0, IsProgram)(program);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveIsRenderbuffer(GLuint renderbuffer)
+{
+ RESOLVE_FUNC(GLboolean, ResolveOES | ResolveEXT, IsRenderbuffer)(renderbuffer);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfSpecialIsShader(GLuint shader)
+{
+ return shader != 0;
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveIsShader(GLuint shader)
+{
+ RESOLVE_FUNC_SPECIAL(GLboolean, 0, IsShader)(shader);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveLinkProgram(GLuint program)
+{
+ RESOLVE_FUNC_VOID(0, LinkProgram)(program);
+}
+
+static void QOPENGLF_APIENTRY qopenglfSpecialReleaseShaderCompiler()
+{
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveReleaseShaderCompiler()
+{
+ RESOLVE_FUNC_SPECIAL_VOID(0, ReleaseShaderCompiler)();
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, RenderbufferStorage)(target, internalformat, width, height);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveSampleCoverage(GLclampf value, GLboolean invert)
+{
+ RESOLVE_FUNC_VOID(ResolveOES | ResolveEXT, SampleCoverage)(value, invert);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
+{
+ RESOLVE_FUNC_VOID(0, ShaderBinary)(n, shaders, binaryformat, binary, length);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
+{
+ RESOLVE_FUNC_VOID(0, ShaderSource)(shader, count, string, length);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, StencilFuncSeparate)(face, func, ref, mask);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveStencilMaskSeparate(GLenum face, GLuint mask)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, StencilMaskSeparate)(face, mask);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, StencilOpSeparate)(face, fail, zfail, zpass);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform1f(GLint location, GLfloat x)
+{
+ RESOLVE_FUNC_VOID(0, Uniform1f)(location, x);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform1fv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform1i(GLint location, GLint x)
+{
+ RESOLVE_FUNC_VOID(0, Uniform1i)(location, x);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform1iv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+ RESOLVE_FUNC_VOID(0, Uniform2f)(location, x, y);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform2fv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform2i(GLint location, GLint x, GLint y)
+{
+ RESOLVE_FUNC_VOID(0, Uniform2i)(location, x, y);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform2iv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ RESOLVE_FUNC_VOID(0, Uniform3f)(location, x, y, z);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform3fv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+ RESOLVE_FUNC_VOID(0, Uniform3i)(location, x, y, z);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform3iv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ RESOLVE_FUNC_VOID(0, Uniform4f)(location, x, y, z, w);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform4fv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ RESOLVE_FUNC_VOID(0, Uniform4i)(location, x, y, z, w);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+ RESOLVE_FUNC_VOID(0, Uniform4iv)(location, count, v);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ RESOLVE_FUNC_VOID(0, UniformMatrix2fv)(location, count, transpose, value);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ RESOLVE_FUNC_VOID(0, UniformMatrix3fv)(location, count, transpose, value);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ RESOLVE_FUNC_VOID(0, UniformMatrix4fv)(location, count, transpose, value);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveUseProgram(GLuint program)
+{
+ RESOLVE_FUNC_VOID(0, UseProgram)(program);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveValidateProgram(GLuint program)
+{
+ RESOLVE_FUNC_VOID(0, ValidateProgram)(program);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib1f(GLuint indx, GLfloat x)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib1f)(indx, x);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib1fv)(indx, values);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib2f)(indx, x, y);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib2fv)(indx, values);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib3f)(indx, x, y, z);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib3fv)(indx, values);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib4f)(indx, x, y, z, w);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttrib4fv)(indx, values);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+{
+ RESOLVE_FUNC_VOID(0, VertexAttribPointer)(indx, size, type, normalized, stride, ptr);
+}
+
+#endif // !QT_OPENGL_ES_2
+
+static GLvoid *QOPENGLF_APIENTRY qopenglfResolveMapBuffer(GLenum target, GLenum access)
+{
+ RESOLVE_FUNC(GLvoid *, ResolveOES, MapBuffer)(target, access);
+}
+
+static GLboolean QOPENGLF_APIENTRY qopenglfResolveUnmapBuffer(GLenum target)
+{
+ RESOLVE_FUNC(GLboolean, ResolveOES, UnmapBuffer)(target);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, BlitFramebuffer)
+ (srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveRenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalFormat,
+ GLsizei width, GLsizei height)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, RenderbufferStorageMultisample)
+ (target, samples, internalFormat, width, height);
+}
+
+static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid *data)
+{
+ RESOLVE_FUNC_VOID(ResolveEXT, GetBufferSubData)
+ (target, offset, size, data);
+}
+
+QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
+{
+#ifndef QT_OPENGL_ES_2
+ ActiveTexture = qopenglfResolveActiveTexture;
+ AttachShader = qopenglfResolveAttachShader;
+ BindAttribLocation = qopenglfResolveBindAttribLocation;
+ BindBuffer = qopenglfResolveBindBuffer;
+ BindFramebuffer = qopenglfResolveBindFramebuffer;
+ BindRenderbuffer = qopenglfResolveBindRenderbuffer;
+ BlendColor = qopenglfResolveBlendColor;
+ BlendEquation = qopenglfResolveBlendEquation;
+ BlendEquationSeparate = qopenglfResolveBlendEquationSeparate;
+ BlendFuncSeparate = qopenglfResolveBlendFuncSeparate;
+ BufferData = qopenglfResolveBufferData;
+ BufferSubData = qopenglfResolveBufferSubData;
+ CheckFramebufferStatus = qopenglfResolveCheckFramebufferStatus;
+ CompileShader = qopenglfResolveCompileShader;
+ CompressedTexImage2D = qopenglfResolveCompressedTexImage2D;
+ CompressedTexSubImage2D = qopenglfResolveCompressedTexSubImage2D;
+ CreateProgram = qopenglfResolveCreateProgram;
+ CreateShader = qopenglfResolveCreateShader;
+ DeleteBuffers = qopenglfResolveDeleteBuffers;
+ DeleteFramebuffers = qopenglfResolveDeleteFramebuffers;
+ DeleteProgram = qopenglfResolveDeleteProgram;
+ DeleteRenderbuffers = qopenglfResolveDeleteRenderbuffers;
+ DeleteShader = qopenglfResolveDeleteShader;
+ DetachShader = qopenglfResolveDetachShader;
+ DisableVertexAttribArray = qopenglfResolveDisableVertexAttribArray;
+ EnableVertexAttribArray = qopenglfResolveEnableVertexAttribArray;
+ FramebufferRenderbuffer = qopenglfResolveFramebufferRenderbuffer;
+ FramebufferTexture2D = qopenglfResolveFramebufferTexture2D;
+ GenBuffers = qopenglfResolveGenBuffers;
+ GenerateMipmap = qopenglfResolveGenerateMipmap;
+ GenFramebuffers = qopenglfResolveGenFramebuffers;
+ GenRenderbuffers = qopenglfResolveGenRenderbuffers;
+ GetActiveAttrib = qopenglfResolveGetActiveAttrib;
+ GetActiveUniform = qopenglfResolveGetActiveUniform;
+ GetAttachedShaders = qopenglfResolveGetAttachedShaders;
+ GetAttribLocation = qopenglfResolveGetAttribLocation;
+ GetBufferParameteriv = qopenglfResolveGetBufferParameteriv;
+ GetFramebufferAttachmentParameteriv = qopenglfResolveGetFramebufferAttachmentParameteriv;
+ GetProgramiv = qopenglfResolveGetProgramiv;
+ GetProgramInfoLog = qopenglfResolveGetProgramInfoLog;
+ GetRenderbufferParameteriv = qopenglfResolveGetRenderbufferParameteriv;
+ GetShaderiv = qopenglfResolveGetShaderiv;
+ GetShaderInfoLog = qopenglfResolveGetShaderInfoLog;
+ GetShaderPrecisionFormat = qopenglfResolveGetShaderPrecisionFormat;
+ GetShaderSource = qopenglfResolveGetShaderSource;
+ GetUniformfv = qopenglfResolveGetUniformfv;
+ GetUniformiv = qopenglfResolveGetUniformiv;
+ GetUniformLocation = qopenglfResolveGetUniformLocation;
+ GetVertexAttribfv = qopenglfResolveGetVertexAttribfv;
+ GetVertexAttribiv = qopenglfResolveGetVertexAttribiv;
+ GetVertexAttribPointerv = qopenglfResolveGetVertexAttribPointerv;
+ IsBuffer = qopenglfResolveIsBuffer;
+ IsFramebuffer = qopenglfResolveIsFramebuffer;
+ IsProgram = qopenglfResolveIsProgram;
+ IsRenderbuffer = qopenglfResolveIsRenderbuffer;
+ IsShader = qopenglfResolveIsShader;
+ LinkProgram = qopenglfResolveLinkProgram;
+ ReleaseShaderCompiler = qopenglfResolveReleaseShaderCompiler;
+ RenderbufferStorage = qopenglfResolveRenderbufferStorage;
+ SampleCoverage = qopenglfResolveSampleCoverage;
+ ShaderBinary = qopenglfResolveShaderBinary;
+ ShaderSource = qopenglfResolveShaderSource;
+ StencilFuncSeparate = qopenglfResolveStencilFuncSeparate;
+ StencilMaskSeparate = qopenglfResolveStencilMaskSeparate;
+ StencilOpSeparate = qopenglfResolveStencilOpSeparate;
+ Uniform1f = qopenglfResolveUniform1f;
+ Uniform1fv = qopenglfResolveUniform1fv;
+ Uniform1i = qopenglfResolveUniform1i;
+ Uniform1iv = qopenglfResolveUniform1iv;
+ Uniform2f = qopenglfResolveUniform2f;
+ Uniform2fv = qopenglfResolveUniform2fv;
+ Uniform2i = qopenglfResolveUniform2i;
+ Uniform2iv = qopenglfResolveUniform2iv;
+ Uniform3f = qopenglfResolveUniform3f;
+ Uniform3fv = qopenglfResolveUniform3fv;
+ Uniform3i = qopenglfResolveUniform3i;
+ Uniform3iv = qopenglfResolveUniform3iv;
+ Uniform4f = qopenglfResolveUniform4f;
+ Uniform4fv = qopenglfResolveUniform4fv;
+ Uniform4i = qopenglfResolveUniform4i;
+ Uniform4iv = qopenglfResolveUniform4iv;
+ UniformMatrix2fv = qopenglfResolveUniformMatrix2fv;
+ UniformMatrix3fv = qopenglfResolveUniformMatrix3fv;
+ UniformMatrix4fv = qopenglfResolveUniformMatrix4fv;
+ UseProgram = qopenglfResolveUseProgram;
+ ValidateProgram = qopenglfResolveValidateProgram;
+ VertexAttrib1f = qopenglfResolveVertexAttrib1f;
+ VertexAttrib1fv = qopenglfResolveVertexAttrib1fv;
+ VertexAttrib2f = qopenglfResolveVertexAttrib2f;
+ VertexAttrib2fv = qopenglfResolveVertexAttrib2fv;
+ VertexAttrib3f = qopenglfResolveVertexAttrib3f;
+ VertexAttrib3fv = qopenglfResolveVertexAttrib3fv;
+ VertexAttrib4f = qopenglfResolveVertexAttrib4f;
+ VertexAttrib4fv = qopenglfResolveVertexAttrib4fv;
+ VertexAttribPointer = qopenglfResolveVertexAttribPointer;
+#endif // !QT_OPENGL_ES_2
+}
+
+QOpenGLExtensionsPrivate::QOpenGLExtensionsPrivate(QOpenGLContext *ctx)
+ : QOpenGLFunctionsPrivate(ctx)
+{
+ MapBuffer = qopenglfResolveMapBuffer;
+ UnmapBuffer = qopenglfResolveUnmapBuffer;
+ BlitFramebuffer = qopenglfResolveBlitFramebuffer;
+ RenderbufferStorageMultisample = qopenglfResolveRenderbufferStorageMultisample;
+ GetBufferSubData = qopenglfResolveGetBufferSubData;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
new file mode 100644
index 0000000000..d3bd580fc7
--- /dev/null
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -0,0 +1,2427 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLFUNCTIONS_H
+#define QOPENGLFUNCTIONS_H
+
+#ifdef __GLEW_H__
+#warning qopenglfunctions.h is not compatible with GLEW, GLEW defines will be undefined
+#warning To use GLEW with Qt, do not include <qopengl.h> or <QOpenGLFunctions> after glew.h
+#endif
+
+#include <QtGui/qopengl.h>
+#include <QtGui/qopenglcontext.h>
+
+//#define Q_ENABLE_OPENGL_FUNCTIONS_DEBUG
+
+#ifdef Q_ENABLE_OPENGL_FUNCTIONS_DEBUG
+#include <stdio.h>
+#define Q_OPENGL_FUNCTIONS_DEBUG \
+ GLenum error = glGetError(); \
+ if (error != GL_NO_ERROR) { \
+ unsigned clamped = qMin(unsigned(error - GL_INVALID_ENUM), 4U); \
+ const char *errors[] = { "GL_INVALID_ENUM", "GL_INVALID_VALUE", "GL_INVALID_OPERATION", "Unknown" }; \
+ printf("GL error at %s:%d: %s\n", __FILE__, __LINE__, errors[clamped]); \
+ int *value = 0; \
+ *value = 0; \
+ }
+#else
+#define Q_OPENGL_FUNCTIONS_DEBUG
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+// Types that aren't defined in all system's gl.h files.
+typedef ptrdiff_t qopengl_GLintptr;
+typedef ptrdiff_t qopengl_GLsizeiptr;
+
+#ifdef Q_WS_WIN
+# define QOPENGLF_APIENTRY APIENTRY
+#endif
+
+#ifndef Q_WS_MAC
+# ifndef QOPENGLF_APIENTRYP
+# ifdef QOPENGLF_APIENTRY
+# define QOPENGLF_APIENTRYP QOPENGLF_APIENTRY *
+# else
+# define QOPENGLF_APIENTRY
+# define QOPENGLF_APIENTRYP *
+# endif
+# endif
+#else
+# define QOPENGLF_APIENTRY
+# define QOPENGLF_APIENTRYP *
+#endif
+
+struct QOpenGLFunctionsPrivate;
+
+// Undefine any macros from GLEW, qopenglextensions_p.h, etc that
+// may interfere with the definition of QOpenGLFunctions.
+#undef glActiveTexture
+#undef glAttachShader
+#undef glBindAttribLocation
+#undef glBindBuffer
+#undef glBindFramebuffer
+#undef glBindRenderbuffer
+#undef glBlendColor
+#undef glBlendEquation
+#undef glBlendEquationSeparate
+#undef glBlendFuncSeparate
+#undef glBufferData
+#undef glBufferSubData
+#undef glCheckFramebufferStatus
+#undef glClearDepthf
+#undef glCompileShader
+#undef glCompressedTexImage2D
+#undef glCompressedTexSubImage2D
+#undef glCreateProgram
+#undef glCreateShader
+#undef glDeleteBuffers
+#undef glDeleteFramebuffers
+#undef glDeleteProgram
+#undef glDeleteRenderbuffers
+#undef glDeleteShader
+#undef glDepthRangef
+#undef glDetachShader
+#undef glDisableVertexAttribArray
+#undef glEnableVertexAttribArray
+#undef glFramebufferRenderbuffer
+#undef glFramebufferTexture2D
+#undef glGenBuffers
+#undef glGenerateMipmap
+#undef glGenFramebuffers
+#undef glGenRenderbuffers
+#undef glGetActiveAttrib
+#undef glGetActiveUniform
+#undef glGetAttachedShaders
+#undef glGetAttribLocation
+#undef glGetBufferParameteriv
+#undef glGetFramebufferAttachmentParameteriv
+#undef glGetProgramiv
+#undef glGetProgramInfoLog
+#undef glGetRenderbufferParameteriv
+#undef glGetShaderiv
+#undef glGetShaderInfoLog
+#undef glGetShaderPrecisionFormat
+#undef glGetShaderSource
+#undef glGetUniformfv
+#undef glGetUniformiv
+#undef glGetUniformLocation
+#undef glGetVertexAttribfv
+#undef glGetVertexAttribiv
+#undef glGetVertexAttribPointerv
+#undef glIsBuffer
+#undef glIsFramebuffer
+#undef glIsProgram
+#undef glIsRenderbuffer
+#undef glIsShader
+#undef glLinkProgram
+#undef glReleaseShaderCompiler
+#undef glRenderbufferStorage
+#undef glSampleCoverage
+#undef glShaderBinary
+#undef glShaderSource
+#undef glStencilFuncSeparate
+#undef glStencilMaskSeparate
+#undef glStencilOpSeparate
+#undef glUniform1f
+#undef glUniform1fv
+#undef glUniform1i
+#undef glUniform1iv
+#undef glUniform2f
+#undef glUniform2fv
+#undef glUniform2i
+#undef glUniform2iv
+#undef glUniform3f
+#undef glUniform3fv
+#undef glUniform3i
+#undef glUniform3iv
+#undef glUniform4f
+#undef glUniform4fv
+#undef glUniform4i
+#undef glUniform4iv
+#undef glUniformMatrix2fv
+#undef glUniformMatrix3fv
+#undef glUniformMatrix4fv
+#undef glUseProgram
+#undef glValidateProgram
+#undef glVertexAttrib1f
+#undef glVertexAttrib1fv
+#undef glVertexAttrib2f
+#undef glVertexAttrib2fv
+#undef glVertexAttrib3f
+#undef glVertexAttrib3fv
+#undef glVertexAttrib4f
+#undef glVertexAttrib4fv
+#undef glVertexAttribPointer
+
+class Q_GUI_EXPORT QOpenGLFunctions
+{
+public:
+ QOpenGLFunctions();
+ QOpenGLFunctions(QOpenGLContext *context);
+ ~QOpenGLFunctions() {}
+
+ 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)
+
+ QOpenGLFunctions::OpenGLFeatures openGLFeatures() const;
+ bool hasOpenGLFeature(QOpenGLFunctions::OpenGLFeature feature) const;
+
+ void initializeGLFunctions();
+
+ 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);
+ GLint 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);
+ GLint 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);
+
+protected:
+ QOpenGLFunctionsPrivate *d_ptr;
+ static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; }
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLFunctions::OpenGLFeatures)
+
+struct QOpenGLFunctionsPrivate
+{
+ QOpenGLFunctionsPrivate(QOpenGLContext *ctx);
+
+#ifndef QT_OPENGL_ES_2
+ void (QOPENGLF_APIENTRYP ActiveTexture)(GLenum texture);
+ void (QOPENGLF_APIENTRYP AttachShader)(GLuint program, GLuint shader);
+ void (QOPENGLF_APIENTRYP BindAttribLocation)(GLuint program, GLuint index, const char* name);
+ void (QOPENGLF_APIENTRYP BindBuffer)(GLenum target, GLuint buffer);
+ void (QOPENGLF_APIENTRYP BindFramebuffer)(GLenum target, GLuint framebuffer);
+ void (QOPENGLF_APIENTRYP BindRenderbuffer)(GLenum target, GLuint renderbuffer);
+ void (QOPENGLF_APIENTRYP BlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+ void (QOPENGLF_APIENTRYP BlendEquation)(GLenum mode);
+ void (QOPENGLF_APIENTRYP BlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha);
+ void (QOPENGLF_APIENTRYP BlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void (QOPENGLF_APIENTRYP BufferData)(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage);
+ void (QOPENGLF_APIENTRYP BufferSubData)(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data);
+ GLenum (QOPENGLF_APIENTRYP CheckFramebufferStatus)(GLenum target);
+ void (QOPENGLF_APIENTRYP CompileShader)(GLuint shader);
+ void (QOPENGLF_APIENTRYP CompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
+ void (QOPENGLF_APIENTRYP CompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
+ GLuint (QOPENGLF_APIENTRYP CreateProgram)();
+ GLuint (QOPENGLF_APIENTRYP CreateShader)(GLenum type);
+ void (QOPENGLF_APIENTRYP DeleteBuffers)(GLsizei n, const GLuint* buffers);
+ void (QOPENGLF_APIENTRYP DeleteFramebuffers)(GLsizei n, const GLuint* framebuffers);
+ void (QOPENGLF_APIENTRYP DeleteProgram)(GLuint program);
+ void (QOPENGLF_APIENTRYP DeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers);
+ void (QOPENGLF_APIENTRYP DeleteShader)(GLuint shader);
+ void (QOPENGLF_APIENTRYP DetachShader)(GLuint program, GLuint shader);
+ void (QOPENGLF_APIENTRYP DisableVertexAttribArray)(GLuint index);
+ void (QOPENGLF_APIENTRYP EnableVertexAttribArray)(GLuint index);
+ void (QOPENGLF_APIENTRYP FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+ void (QOPENGLF_APIENTRYP FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ void (QOPENGLF_APIENTRYP GenBuffers)(GLsizei n, GLuint* buffers);
+ void (QOPENGLF_APIENTRYP GenerateMipmap)(GLenum target);
+ void (QOPENGLF_APIENTRYP GenFramebuffers)(GLsizei n, GLuint* framebuffers);
+ void (QOPENGLF_APIENTRYP GenRenderbuffers)(GLsizei n, GLuint* renderbuffers);
+ void (QOPENGLF_APIENTRYP GetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (QOPENGLF_APIENTRYP GetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name);
+ void (QOPENGLF_APIENTRYP GetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+ GLint (QOPENGLF_APIENTRYP GetAttribLocation)(GLuint program, const char* name);
+ void (QOPENGLF_APIENTRYP GetBufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetProgramiv)(GLuint program, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (QOPENGLF_APIENTRYP GetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetShaderiv)(GLuint shader, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog);
+ void (QOPENGLF_APIENTRYP GetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+ void (QOPENGLF_APIENTRYP GetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, char* source);
+ void (QOPENGLF_APIENTRYP GetUniformfv)(GLuint program, GLint location, GLfloat* params);
+ void (QOPENGLF_APIENTRYP GetUniformiv)(GLuint program, GLint location, GLint* params);
+ GLint (QOPENGLF_APIENTRYP GetUniformLocation)(GLuint program, const char* name);
+ void (QOPENGLF_APIENTRYP GetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params);
+ void (QOPENGLF_APIENTRYP GetVertexAttribiv)(GLuint index, GLenum pname, GLint* params);
+ void (QOPENGLF_APIENTRYP GetVertexAttribPointerv)(GLuint index, GLenum pname, void** pointer);
+ GLboolean (QOPENGLF_APIENTRYP IsBuffer)(GLuint buffer);
+ GLboolean (QOPENGLF_APIENTRYP IsFramebuffer)(GLuint framebuffer);
+ GLboolean (QOPENGLF_APIENTRYP IsProgram)(GLuint program);
+ GLboolean (QOPENGLF_APIENTRYP IsRenderbuffer)(GLuint renderbuffer);
+ GLboolean (QOPENGLF_APIENTRYP IsShader)(GLuint shader);
+ void (QOPENGLF_APIENTRYP LinkProgram)(GLuint program);
+ void (QOPENGLF_APIENTRYP ReleaseShaderCompiler)();
+ void (QOPENGLF_APIENTRYP RenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ void (QOPENGLF_APIENTRYP SampleCoverage)(GLclampf value, GLboolean invert);
+ void (QOPENGLF_APIENTRYP ShaderBinary)(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
+ void (QOPENGLF_APIENTRYP ShaderSource)(GLuint shader, GLsizei count, const char** string, const GLint* length);
+ void (QOPENGLF_APIENTRYP StencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask);
+ void (QOPENGLF_APIENTRYP StencilMaskSeparate)(GLenum face, GLuint mask);
+ void (QOPENGLF_APIENTRYP StencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ void (QOPENGLF_APIENTRYP Uniform1f)(GLint location, GLfloat x);
+ void (QOPENGLF_APIENTRYP Uniform1fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (QOPENGLF_APIENTRYP Uniform1i)(GLint location, GLint x);
+ void (QOPENGLF_APIENTRYP Uniform1iv)(GLint location, GLsizei count, const GLint* v);
+ void (QOPENGLF_APIENTRYP Uniform2f)(GLint location, GLfloat x, GLfloat y);
+ void (QOPENGLF_APIENTRYP Uniform2fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (QOPENGLF_APIENTRYP Uniform2i)(GLint location, GLint x, GLint y);
+ void (QOPENGLF_APIENTRYP Uniform2iv)(GLint location, GLsizei count, const GLint* v);
+ void (QOPENGLF_APIENTRYP Uniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z);
+ void (QOPENGLF_APIENTRYP Uniform3fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (QOPENGLF_APIENTRYP Uniform3i)(GLint location, GLint x, GLint y, GLint z);
+ void (QOPENGLF_APIENTRYP Uniform3iv)(GLint location, GLsizei count, const GLint* v);
+ void (QOPENGLF_APIENTRYP Uniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (QOPENGLF_APIENTRYP Uniform4fv)(GLint location, GLsizei count, const GLfloat* v);
+ void (QOPENGLF_APIENTRYP Uniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w);
+ void (QOPENGLF_APIENTRYP Uniform4iv)(GLint location, GLsizei count, const GLint* v);
+ void (QOPENGLF_APIENTRYP UniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (QOPENGLF_APIENTRYP UniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (QOPENGLF_APIENTRYP UniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ void (QOPENGLF_APIENTRYP UseProgram)(GLuint program);
+ void (QOPENGLF_APIENTRYP ValidateProgram)(GLuint program);
+ void (QOPENGLF_APIENTRYP VertexAttrib1f)(GLuint indx, GLfloat x);
+ void (QOPENGLF_APIENTRYP VertexAttrib1fv)(GLuint indx, const GLfloat* values);
+ void (QOPENGLF_APIENTRYP VertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y);
+ void (QOPENGLF_APIENTRYP VertexAttrib2fv)(GLuint indx, const GLfloat* values);
+ void (QOPENGLF_APIENTRYP VertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+ void (QOPENGLF_APIENTRYP VertexAttrib3fv)(GLuint indx, const GLfloat* values);
+ void (QOPENGLF_APIENTRYP VertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void (QOPENGLF_APIENTRYP VertexAttrib4fv)(GLuint indx, const GLfloat* values);
+ void (QOPENGLF_APIENTRYP VertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
+#endif
+};
+
+inline void QOpenGLFunctions::glActiveTexture(GLenum texture)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glActiveTexture(texture);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->ActiveTexture(texture);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glAttachShader(GLuint program, GLuint shader)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glAttachShader(program, shader);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->AttachShader(program, shader);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBindAttribLocation(GLuint program, GLuint index, const char* name)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBindAttribLocation(program, index, name);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BindAttribLocation(program, index, name);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBindBuffer(GLenum target, GLuint buffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBindBuffer(target, buffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BindBuffer(target, buffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBindFramebuffer(GLenum target, GLuint framebuffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBindFramebuffer(target, framebuffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BindFramebuffer(target, framebuffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBindRenderbuffer(target, renderbuffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BindRenderbuffer(target, renderbuffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBlendColor(red, green, blue, alpha);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BlendColor(red, green, blue, alpha);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBlendEquation(GLenum mode)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBlendEquation(mode);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BlendEquation(mode);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBlendEquationSeparate(modeRGB, modeAlpha);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BlendEquationSeparate(modeRGB, modeAlpha);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBufferData(GLenum target, qopengl_GLsizeiptr size, const void* data, GLenum usage)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBufferData(target, size, data, usage);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BufferData(target, size, data, usage);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glBufferSubData(GLenum target, qopengl_GLintptr offset, qopengl_GLsizeiptr size, const void* data)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glBufferSubData(target, offset, size, data);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->BufferSubData(target, offset, size, data);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLenum QOpenGLFunctions::glCheckFramebufferStatus(GLenum target)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLenum result = ::glCheckFramebufferStatus(target);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLenum result = d_ptr->CheckFramebufferStatus(target);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLFunctions::glClearDepthf(GLclampf depth)
+{
+#ifndef QT_OPENGL_ES
+ ::glClearDepth(depth);
+#else
+ ::glClearDepthf(depth);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glCompileShader(GLuint shader)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glCompileShader(shader);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->CompileShader(shader);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLuint QOpenGLFunctions::glCreateProgram()
+{
+#if defined(QT_OPENGL_ES_2)
+ GLuint result = ::glCreateProgram();
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLuint result = d_ptr->CreateProgram();
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLuint QOpenGLFunctions::glCreateShader(GLenum type)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLuint result = ::glCreateShader(type);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLuint result = d_ptr->CreateShader(type);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLFunctions::glDeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDeleteBuffers(n, buffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DeleteBuffers(n, buffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDeleteFramebuffers(n, framebuffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DeleteFramebuffers(n, framebuffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDeleteProgram(GLuint program)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDeleteProgram(program);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DeleteProgram(program);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDeleteRenderbuffers(n, renderbuffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DeleteRenderbuffers(n, renderbuffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDeleteShader(GLuint shader)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDeleteShader(shader);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DeleteShader(shader);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDepthRangef(GLclampf zNear, GLclampf zFar)
+{
+#ifndef QT_OPENGL_ES
+ ::glDepthRange(zNear, zFar);
+#else
+ ::glDepthRangef(zNear, zFar);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDetachShader(GLuint program, GLuint shader)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDetachShader(program, shader);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DetachShader(program, shader);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glDisableVertexAttribArray(GLuint index)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glDisableVertexAttribArray(index);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->DisableVertexAttribArray(index);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glEnableVertexAttribArray(GLuint index)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glEnableVertexAttribArray(index);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->EnableVertexAttribArray(index);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glFramebufferTexture2D(target, attachment, textarget, texture, level);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->FramebufferTexture2D(target, attachment, textarget, texture, level);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGenBuffers(GLsizei n, GLuint* buffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGenBuffers(n, buffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GenBuffers(n, buffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGenerateMipmap(GLenum target)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGenerateMipmap(target);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GenerateMipmap(target);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGenFramebuffers(n, framebuffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GenFramebuffers(n, framebuffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGenRenderbuffers(n, renderbuffers);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GenRenderbuffers(n, renderbuffers);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetActiveAttrib(program, index, bufsize, length, size, type, name);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetActiveAttrib(program, index, bufsize, length, size, type, name);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetActiveUniform(program, index, bufsize, length, size, type, name);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetActiveUniform(program, index, bufsize, length, size, type, name);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetAttachedShaders(program, maxcount, count, shaders);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetAttachedShaders(program, maxcount, count, shaders);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLint QOpenGLFunctions::glGetAttribLocation(GLuint program, const char* name)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint result = ::glGetAttribLocation(program, name);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLint result = d_ptr->GetAttribLocation(program, name);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLFunctions::glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetBufferParameteriv(target, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetBufferParameteriv(target, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetProgramiv(program, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetProgramiv(program, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetProgramInfoLog(program, bufsize, length, infolog);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetProgramInfoLog(program, bufsize, length, infolog);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetRenderbufferParameteriv(target, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetRenderbufferParameteriv(target, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetShaderiv(shader, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetShaderiv(shader, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetShaderInfoLog(shader, bufsize, length, infolog);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetShaderInfoLog(shader, bufsize, length, infolog);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetShaderSource(shader, bufsize, length, source);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetShaderSource(shader, bufsize, length, source);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetUniformfv(program, location, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetUniformfv(program, location, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetUniformiv(GLuint program, GLint location, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetUniformiv(program, location, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetUniformiv(program, location, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLint QOpenGLFunctions::glGetUniformLocation(GLuint program, const char* name)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint result = ::glGetUniformLocation(program, name);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLint result = d_ptr->GetUniformLocation(program, name);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLFunctions::glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetVertexAttribfv(index, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetVertexAttribfv(index, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetVertexAttribiv(index, pname, params);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetVertexAttribiv(index, pname, params);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glGetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glGetVertexAttribPointerv(index, pname, pointer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->GetVertexAttribPointerv(index, pname, pointer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLboolean QOpenGLFunctions::glIsBuffer(GLuint buffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLboolean result = ::glIsBuffer(buffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLboolean result = d_ptr->IsBuffer(buffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLboolean QOpenGLFunctions::glIsFramebuffer(GLuint framebuffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLboolean result = ::glIsFramebuffer(framebuffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLboolean result = d_ptr->IsFramebuffer(framebuffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLboolean QOpenGLFunctions::glIsProgram(GLuint program)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLboolean result = ::glIsProgram(program);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLboolean result = d_ptr->IsProgram(program);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLboolean QOpenGLFunctions::glIsRenderbuffer(GLuint renderbuffer)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLboolean result = ::glIsRenderbuffer(renderbuffer);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLboolean result = d_ptr->IsRenderbuffer(renderbuffer);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLboolean QOpenGLFunctions::glIsShader(GLuint shader)
+{
+#if defined(QT_OPENGL_ES_2)
+ GLboolean result = ::glIsShader(shader);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ GLboolean result = d_ptr->IsShader(shader);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLFunctions::glLinkProgram(GLuint program)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glLinkProgram(program);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->LinkProgram(program);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glReleaseShaderCompiler()
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glReleaseShaderCompiler();
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->ReleaseShaderCompiler();
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glRenderbufferStorage(target, internalformat, width, height);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->RenderbufferStorage(target, internalformat, width, height);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glSampleCoverage(GLclampf value, GLboolean invert)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glSampleCoverage(value, invert);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->SampleCoverage(value, invert);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glShaderBinary(n, shaders, binaryformat, binary, length);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->ShaderBinary(n, shaders, binaryformat, binary, length);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glShaderSource(shader, count, string, length);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->ShaderSource(shader, count, string, length);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glStencilFuncSeparate(face, func, ref, mask);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->StencilFuncSeparate(face, func, ref, mask);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glStencilMaskSeparate(GLenum face, GLuint mask)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glStencilMaskSeparate(face, mask);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->StencilMaskSeparate(face, mask);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glStencilOpSeparate(face, fail, zfail, zpass);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->StencilOpSeparate(face, fail, zfail, zpass);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform1f(GLint location, GLfloat x)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform1f(location, x);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform1f(location, x);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform1fv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform1fv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform1i(GLint location, GLint x)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform1i(location, x);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform1i(location, x);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform1iv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform1iv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform2f(GLint location, GLfloat x, GLfloat y)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform2f(location, x, y);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform2f(location, x, y);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform2fv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform2fv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform2i(GLint location, GLint x, GLint y)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform2i(location, x, y);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform2i(location, x, y);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform2iv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform2iv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform3f(location, x, y, z);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform3f(location, x, y, z);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform3fv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform3fv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform3i(location, x, y, z);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform3i(location, x, y, z);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform3iv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform3iv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform4f(location, x, y, z, w);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform4f(location, x, y, z, w);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform4fv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform4fv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform4i(location, x, y, z, w);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform4i(location, x, y, z, w);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniform4iv(location, count, v);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->Uniform4iv(location, count, v);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniformMatrix2fv(location, count, transpose, value);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->UniformMatrix2fv(location, count, transpose, value);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniformMatrix3fv(location, count, transpose, value);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->UniformMatrix3fv(location, count, transpose, value);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUniformMatrix4fv(location, count, transpose, value);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->UniformMatrix4fv(location, count, transpose, value);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glUseProgram(GLuint program)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glUseProgram(program);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->UseProgram(program);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glValidateProgram(GLuint program)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glValidateProgram(program);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->ValidateProgram(program);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib1f(GLuint indx, GLfloat x)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib1f(indx, x);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib1f(indx, x);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib1fv(GLuint indx, const GLfloat* values)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib1fv(indx, values);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib1fv(indx, values);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib2f(indx, x, y);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib2f(indx, x, y);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib2fv(GLuint indx, const GLfloat* values)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib2fv(indx, values);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib2fv(indx, values);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib3f(indx, x, y, z);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib3f(indx, x, y, z);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib3fv(GLuint indx, const GLfloat* values)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib3fv(indx, values);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib3fv(indx, values);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib4f(indx, x, y, z, w);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib4f(indx, x, y, z, w);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttrib4fv(GLuint indx, const GLfloat* values)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttrib4fv(indx, values);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttrib4fv(indx, values);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+{
+#if defined(QT_OPENGL_ES_2)
+ ::glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+#else
+ Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
+ d_ptr->VertexAttribPointer(indx, size, type, normalized, stride, ptr);
+#endif
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+#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
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/opengl/qopenglgradientcache.cpp b/src/gui/opengl/qopenglgradientcache.cpp
new file mode 100644
index 0000000000..f8d61cd620
--- /dev/null
+++ b/src/gui/opengl/qopenglgradientcache.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglgradientcache_p.h"
+#include <private/qdrawhelper_p.h>
+#include <private/qopenglcontext_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGL2GradientCacheWrapper
+{
+public:
+ QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context) {
+ QMutexLocker lock(&m_mutex);
+ return m_resource.value<QOpenGL2GradientCache>(context);
+ }
+
+private:
+ QOpenGLMultiGroupSharedResource m_resource;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QOpenGL2GradientCacheWrapper, qt_gradient_caches)
+
+QOpenGL2GradientCache::QOpenGL2GradientCache(QOpenGLContext *ctx)
+ : QOpenGLSharedResource(ctx->shareGroup())
+{
+}
+
+QOpenGL2GradientCache::~QOpenGL2GradientCache()
+{
+ cache.clear();
+}
+
+QOpenGL2GradientCache *QOpenGL2GradientCache::cacheForContext(QOpenGLContext *context)
+{
+ return qt_gradient_caches()->cacheForContext(context);
+}
+
+void QOpenGL2GradientCache::invalidateResource()
+{
+ QMutexLocker lock(&m_mutex);
+ cache.clear();
+}
+
+void QOpenGL2GradientCache::freeResource(QOpenGLContext *)
+{
+ cleanCache();
+}
+
+void QOpenGL2GradientCache::cleanCache()
+{
+ QMutexLocker lock(&m_mutex);
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constBegin();
+ for (; it != cache.constEnd(); ++it) {
+ const CacheInfo &cache_info = it.value();
+ glDeleteTextures(1, &cache_info.texId);
+ }
+ cache.clear();
+}
+
+GLuint QOpenGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity)
+{
+ QMutexLocker lock(&m_mutex);
+ quint64 hash_val = 0;
+
+ QGradientStops stops = gradient.stops();
+ for (int i = 0; i < stops.size() && i <= 2; i++)
+ hash_val += stops[i].second.rgba();
+
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
+
+ if (it == cache.constEnd())
+ return addCacheElement(hash_val, gradient, opacity);
+ else {
+ do {
+ const CacheInfo &cache_info = it.value();
+ if (cache_info.stops == stops && cache_info.opacity == opacity
+ && cache_info.interpolationMode == gradient.interpolationMode())
+ {
+ return cache_info.texId;
+ }
+ ++it;
+ } while (it != cache.constEnd() && it.key() == hash_val);
+ // an exact match for these stops and opacity was not found, create new cache
+ return addCacheElement(hash_val, gradient, opacity);
+ }
+}
+
+
+GLuint QOpenGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
+{
+ if (cache.size() == maxCacheSize()) {
+ int elem_to_remove = qrand() % maxCacheSize();
+ quint64 key = cache.keys()[elem_to_remove];
+
+ // need to call glDeleteTextures on each removed cache entry:
+ QOpenGLGradientColorTableHash::const_iterator it = cache.constFind(key);
+ do {
+ glDeleteTextures(1, &it.value().texId);
+ } while (++it != cache.constEnd() && it.key() == key);
+ cache.remove(key); // may remove more than 1, but OK
+ }
+
+ CacheInfo cache_entry(gradient.stops(), opacity, gradient.interpolationMode());
+ uint buffer[1024];
+ generateGradientColorTable(gradient, buffer, paletteSize(), opacity);
+ glGenTextures(1, &cache_entry.texId);
+ glBindTexture(GL_TEXTURE_2D, cache_entry.texId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, paletteSize(), 1,
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ return cache.insert(hash_val, cache_entry).value().texId;
+}
+
+
+// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86).
+// Qt always stores in ARGB reguardless of the byte-order the mancine uses.
+static inline uint qtToGlColor(uint c)
+{
+ uint o;
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+ o = (c & 0xff00ff00) // alpha & green already in the right place
+ | ((c >> 16) & 0x000000ff) // red
+ | ((c << 16) & 0x00ff0000); // blue
+#else //Q_BIG_ENDIAN
+ o = (c << 8)
+ | ((c >> 24) & 0x000000ff);
+#endif // Q_BYTE_ORDER
+ return o;
+}
+
+//TODO: Let GL generate the texture using an FBO
+void QOpenGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
+{
+ int pos = 0;
+ QGradientStops s = gradient.stops();
+ QVector<uint> colors(s.size());
+
+ for (int i = 0; i < s.size(); ++i)
+ colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
+
+ bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
+
+ uint alpha = qRound(opacity * 256);
+ uint current_color = ARGB_COMBINE_ALPHA(colors[0], alpha);
+ qreal incr = 1.0 / qreal(size);
+ qreal fpos = 1.5 * incr;
+ colorTable[pos++] = qtToGlColor(PREMUL(current_color));
+
+ while (fpos <= s.first().first) {
+ colorTable[pos] = colorTable[pos - 1];
+ pos++;
+ fpos += incr;
+ }
+
+ if (colorInterpolation)
+ current_color = PREMUL(current_color);
+
+ for (int i = 0; i < s.size() - 1; ++i) {
+ qreal delta = 1/(s[i+1].first - s[i].first);
+ uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
+ if (colorInterpolation)
+ next_color = PREMUL(next_color);
+
+ while (fpos < s[i+1].first && pos < size) {
+ int dist = int(256 * ((fpos - s[i].first) * delta));
+ int idist = 256 - dist;
+ if (colorInterpolation)
+ colorTable[pos] = qtToGlColor(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist));
+ else
+ colorTable[pos] = qtToGlColor(PREMUL(INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist)));
+ ++pos;
+ fpos += incr;
+ }
+ current_color = next_color;
+ }
+
+ Q_ASSERT(s.size() > 0);
+
+ uint last_color = qtToGlColor(PREMUL(ARGB_COMBINE_ALPHA(colors[s.size() - 1], alpha)));
+ for (;pos < size; ++pos)
+ colorTable[pos] = last_color;
+
+ // Make sure the last color stop is represented at the end of the table
+ colorTable[size-1] = last_color;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglgradientcache_p.h b/src/gui/opengl/qopenglgradientcache_p.h
new file mode 100644
index 0000000000..53abf221d2
--- /dev/null
+++ b/src/gui/opengl/qopenglgradientcache_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QMultiHash>
+#include <QObject>
+#include <QtGui/QtGui>
+#include <private/qopenglcontext_p.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGL2GradientCache : public QOpenGLSharedResource
+{
+ struct CacheInfo
+ {
+ inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) :
+ stops(s), opacity(op), interpolationMode(mode) {}
+
+ GLuint texId;
+ QGradientStops stops;
+ qreal opacity;
+ QGradient::InterpolationMode interpolationMode;
+ };
+
+ typedef QMultiHash<quint64, CacheInfo> QOpenGLGradientColorTableHash;
+
+public:
+ static QOpenGL2GradientCache *cacheForContext(QOpenGLContext *context);
+
+ QOpenGL2GradientCache(QOpenGLContext *);
+ ~QOpenGL2GradientCache();
+
+ GLuint getBuffer(const QGradient &gradient, qreal opacity);
+ inline int paletteSize() const { return 1024; }
+
+ void invalidateResource();
+ void freeResource(QOpenGLContext *ctx);
+
+private:
+ inline int maxCacheSize() const { return 60; }
+ inline void generateGradientColorTable(const QGradient& gradient,
+ uint *colorTable,
+ int size, qreal opacity) const;
+ GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity);
+ void cleanCache();
+
+ QOpenGLGradientColorTableHash cache;
+ QMutex m_mutex;
+};
+
+QT_END_NAMESPACE
+
diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp
new file mode 100644
index 0000000000..e3ff5ae1f9
--- /dev/null
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qopenglpaintdevice_p.h>
+#include <private/qopenglcontext_p.h>
+#include <private/qopenglframebufferobject_p.h>
+
+#include <qopenglfunctions.h>
+
+QT_BEGIN_NAMESPACE
+
+QOpenGLPaintDevice::QOpenGLPaintDevice()
+ : m_thisFBO(0)
+{
+}
+
+QOpenGLPaintDevice::~QOpenGLPaintDevice()
+{
+}
+
+int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch(metric) {
+ case PdmWidth:
+ return size().width();
+ case PdmHeight:
+ return size().height();
+ case PdmDepth: {
+ const QSurfaceFormat f = format();
+ return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
+ }
+ default:
+ qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
+ return 0;
+ }
+}
+
+void QOpenGLPaintDevice::beginPaint()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ // 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()->current_fbo = m_thisFBO;
+ QOpenGLFunctions(ctx).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 QOpenGLFramebufferObject::release(),
+ // painting will revert to the window surface's fbo.
+ ctx->d_func()->default_fbo = m_thisFBO;
+}
+
+void QOpenGLPaintDevice::ensureActiveTarget()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ if (ctx->d_func()->current_fbo != m_thisFBO) {
+ ctx->d_func()->current_fbo = m_thisFBO;
+ QOpenGLFunctions(ctx).glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
+ }
+
+ ctx->d_func()->default_fbo = m_thisFBO;
+}
+
+void QOpenGLPaintDevice::endPaint()
+{
+ // Make sure the FBO bound at beginPaint is re-bound again here:
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+
+ if (m_previousFBO != ctx->d_func()->current_fbo) {
+ ctx->d_func()->current_fbo = m_previousFBO;
+ QOpenGLFunctions(ctx).glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO);
+ }
+
+ ctx->d_func()->default_fbo = 0;
+}
+
+bool QOpenGLPaintDevice::isFlipped() const
+{
+ return false;
+}
+
+// returns the QOpenGLPaintDevice for the given QPaintDevice
+QOpenGLPaintDevice* QOpenGLPaintDevice::getDevice(QPaintDevice* pd)
+{
+ QOpenGLPaintDevice* glpd = 0;
+
+ switch(pd->devType()) {
+ case QInternal::FramebufferObject:
+ glpd = &(static_cast<QOpenGLFramebufferObject*>(pd)->d_func()->glDevice);
+ break;
+ case QInternal::Pixmap: {
+ qWarning("Pixmap type not supported for GL rendering");
+ break;
+ }
+ default:
+ qWarning("QOpenGLPaintDevice::getDevice() - Unknown device type %d", pd->devType());
+ break;
+ }
+
+ return glpd;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglpaintdevice_p.h b/src/gui/opengl/qopenglpaintdevice_p.h
new file mode 100644
index 0000000000..492bc1649a
--- /dev/null
+++ b/src/gui/opengl/qopenglpaintdevice_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGLPAINTDEVICE_P_H
+#define QOPENGLPAINTDEVICE_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 QtGui module. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <qpaintdevice.h>
+#include <QtGui/qopengl.h>
+#include <QtGui/qopenglcontext.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QOpenGLPaintDevice : public QPaintDevice
+{
+public:
+ QOpenGLPaintDevice();
+ virtual ~QOpenGLPaintDevice();
+
+ int devType() const {return QInternal::OpenGL;}
+
+ virtual void beginPaint();
+ virtual void ensureActiveTarget();
+ virtual void endPaint();
+
+ virtual QOpenGLContextGroup *group() const = 0;
+
+ virtual QSurfaceFormat format() const = 0;
+ virtual QSize size() const = 0;
+
+ virtual bool alphaRequested() const = 0;
+ virtual bool isFlipped() const;
+
+ // returns the QOpenGLPaintDevice for the given QPaintDevice
+ static QOpenGLPaintDevice* getDevice(QPaintDevice*);
+
+protected:
+ int metric(QPaintDevice::PaintDeviceMetric metric) const;
+ GLuint m_previousFBO;
+ GLuint m_thisFBO;
+};
+
+
+#if 0
+// Wraps a QOpenGLWidget
+class QOpenGLWidget;
+class Q_GUI_EXPORT QOpenGLWidgetGLPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLWidgetGLPaintDevice();
+
+ virtual QPaintEngine* paintEngine() const;
+
+ // QOpenGLWidgets need to do swapBufers in endPaint:
+ virtual void beginPaint();
+ virtual void endPaint();
+ virtual QSize size() const;
+ virtual QOpenGLContext* context() const;
+
+ void setWidget(QOpenGLWidget*);
+
+private:
+ friend class QOpenGLWidget;
+ QOpenGLWidget *glWidget;
+};
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QOPENGLPAINTDEVICE_P_H
diff --git a/src/gui/opengl/qopenglshadercache_meego_p.h b/src/gui/opengl/qopenglshadercache_meego_p.h
new file mode 100644
index 0000000000..86a8a861da
--- /dev/null
+++ b/src/gui/opengl/qopenglshadercache_meego_p.h
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QOPENGLSHADERCACHE_MEEGO_P_H
+#define QOPENGLSHADERCACHE_MEEGO_P_H
+
+#include <QtCore/qopenglobal.h>
+
+#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2)
+
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qsharedmemory.h>
+#include <QtCore/qsystemsemaphore.h>
+
+#ifndef QT_BOOTSTRAPPED
+# include <GLES2/gl2ext.h>
+#endif
+#if defined(QT_DEBUG) || defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE)
+# include <syslog.h>
+#endif
+
+QT_BEGIN_HEADER
+
+/*
+ This cache stores internal Qt shader programs in shared memory.
+
+ This header file is ugly on purpose and can only be included once. It is only to be used
+ for the internal shader cache, not as a generic cache for anyone's shaders.
+
+ The cache stores either ShaderCacheMaxEntries shader programs or ShaderCacheDataSize kilobytes
+ of shader programs, whatever limit is reached first.
+
+ The layout of the cache is as outlined in the CachedShaders struct. After some
+ integers, an array of headers is reserved, then comes the space for the actual binaries.
+
+ Shader Programs are identified by the md5sum of their frag and vertex shader source code.
+
+ Shader Programs are never removed. The cache never shrinks or re-shuffles. This is done
+ on purpose to ensure minimum amount of locking, no alignment problems and very few write
+ operations.
+
+ Note: Locking the shader cache could be expensive, because the entire system might hang.
+ That's why the cache is immutable to minimize the time we need to keep it locked.
+
+ Why is it Meego specific?
+
+ First, the size is chosen so that it fits to generic meego usage. Second, on Meego, there's
+ always at least one Qt application active (the launcher), so the cache will never be destroyed.
+ Only when the last Qt app exits, the cache dies, which should only be when someone kills the
+ X11 server. And last but not least it was only tested with Meego's SGX driver.
+
+ There's a small tool in src/opengl/util/meego that dumps the contents of the cache.
+ */
+
+// anonymous namespace, prevent exporting of the private symbols
+namespace
+{
+
+struct CachedShaderHeader
+{
+ /* the index in the data[] member of CachedShaders */
+ int index;
+ /* the size of the binary shader */
+ GLsizei size;
+ /* the format of the binary shader */
+ GLenum format;
+ /* the md5sum of the frag+vertex shaders */
+ char md5Sum[16];
+};
+
+enum
+{
+ /* The maximum amount of shader programs the cache can hold */
+ ShaderCacheMaxEntries = 20
+};
+
+typedef CachedShaderHeader CachedShaderHeaders[ShaderCacheMaxEntries];
+
+enum
+{
+ // ShaderCacheDataSize is 20k minus the other data members of CachedShaders
+ ShaderCacheDataSize = 1024 * ShaderCacheMaxEntries - sizeof(CachedShaderHeaders) - 2 * sizeof(int)
+};
+
+struct CachedShaders
+{
+ /* How much space is still available in the cache */
+ inline int availableSize() const { return ShaderCacheDataSize - dataSize; }
+
+ /* The current amount of cached shaders */
+ int shaderCount;
+
+ /* The current amount (in bytes) of cached data */
+ int dataSize;
+
+ /* The headers describing the shaders */
+ CachedShaderHeaders headers;
+
+ /* The actual binary data of the shader programs */
+ char data[ShaderCacheDataSize];
+};
+
+//#define QT_DEBUG_SHADER_CACHE
+#ifdef QT_DEBUG_SHADER_CACHE
+static QDebug shaderCacheDebug()
+{
+ return QDebug(QtDebugMsg);
+}
+#else
+static inline QNoDebug shaderCacheDebug() { return QNoDebug(); }
+#endif
+
+class ShaderCacheSharedMemory
+{
+public:
+ ShaderCacheSharedMemory()
+ : shm(QLatin1String("qt_gles2_shadercache_" QT_VERSION_STR))
+ {
+ // we need a system semaphore here, since cache creation and initialization must be atomic
+ QSystemSemaphore attachSemaphore(QLatin1String("qt_gles2_shadercache_mutex_" QT_VERSION_STR), 1);
+
+ if (!attachSemaphore.acquire()) {
+ shaderCacheDebug() << "Unable to require shader cache semaphore:" << attachSemaphore.errorString();
+ return;
+ }
+
+ if (shm.attach()) {
+ // success!
+ shaderCacheDebug() << "Attached to shader cache";
+ } else {
+
+ // no cache exists - create and initialize it
+ if (shm.create(sizeof(CachedShaders))) {
+ shaderCacheDebug() << "Created new shader cache";
+ initializeCache();
+ } else {
+ shaderCacheDebug() << "Unable to create shader cache:" << shm.errorString();
+ }
+ }
+
+ attachSemaphore.release();
+ }
+
+ inline bool isAttached() const { return shm.isAttached(); }
+
+ inline bool lock() { return shm.lock(); }
+ inline bool unlock() { return shm.unlock(); }
+ inline void *data() { return shm.data(); }
+ inline QString errorString() { return shm.errorString(); }
+
+ ~ShaderCacheSharedMemory()
+ {
+ if (!shm.detach())
+ shaderCacheDebug() << "Unable to detach shader cache" << shm.errorString();
+ }
+
+private:
+ void initializeCache()
+ {
+ // no need to lock the shared memory since we're already protected by the
+ // attach system semaphore.
+
+ void *data = shm.data();
+ Q_ASSERT(data);
+
+ memset(data, 0, sizeof(CachedShaders));
+ }
+
+ QSharedMemory shm;
+};
+
+class ShaderCacheLocker
+{
+public:
+ inline ShaderCacheLocker(ShaderCacheSharedMemory *cache)
+ : shm(cache->lock() ? cache : (ShaderCacheSharedMemory *)0)
+ {
+ if (!shm)
+ shaderCacheDebug() << "Unable to lock shader cache" << cache->errorString();
+ }
+
+ inline bool isLocked() const { return shm; }
+
+ inline ~ShaderCacheLocker()
+ {
+ if (!shm)
+ return;
+ if (!shm->unlock())
+ shaderCacheDebug() << "Unable to unlock shader cache" << shm->errorString();
+ }
+
+private:
+ ShaderCacheSharedMemory *shm;
+};
+
+#ifdef QT_BOOTSTRAPPED
+} // end namespace
+#else
+
+static void traceCacheOverflow(const char *message)
+{
+#if defined(QT_DEBUG) || defined (QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE)
+ openlog(qPrintable(QCoreApplication::applicationName()), LOG_PID | LOG_ODELAY, LOG_USER);
+ syslog(LOG_DEBUG, message);
+ closelog();
+#endif
+ shaderCacheDebug() << message;
+}
+
+Q_GLOBAL_STATIC(ShaderCacheSharedMemory, shaderCacheSharedMemory)
+
+/*
+ Finds the index of the shader program identified by md5Sum in the cache.
+ Note: Does NOT lock the cache for reading, the cache must already be locked!
+
+ Returns -1 when no shader was found.
+ */
+static int qt_cache_index_unlocked(const QByteArray &md5Sum, CachedShaders *cache)
+{
+ for (int i = 0; i < cache->shaderCount; ++i) {
+ if (qstrncmp(md5Sum.constData(), cache->headers[i].md5Sum, 16) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/* Returns the index of the shader identified by md5Sum */
+static int qt_cache_index(const QByteArray &md5Sum)
+{
+ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
+ if (!shm || !shm->isAttached())
+ return false;
+
+ Q_ASSERT(md5Sum.length() == 16);
+
+ ShaderCacheLocker locker(shm);
+ if (!locker.isLocked())
+ return false;
+
+ void *data = shm->data();
+ Q_ASSERT(data);
+
+ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
+
+ return qt_cache_index_unlocked(md5Sum, cache);
+}
+
+/* Loads the cached shader at index \a shaderIndex into \a program
+ * Note: Since the cache is immutable, this operation doesn't lock the shared memory.
+ */
+static bool qt_cached_shader(QOpenGLShaderProgram *program, QOpenGLContext *ctx, int shaderIndex)
+{
+ Q_ASSERT(shaderIndex >= 0 && shaderIndex <= ShaderCacheMaxEntries);
+ Q_ASSERT(program);
+
+ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
+ if (!shm || !shm->isAttached())
+ return false;
+
+ void *data = shm->data();
+ Q_ASSERT(data);
+
+ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
+
+ shaderCacheDebug() << "fetching cached shader at index" << shaderIndex
+ << "dataIndex" << cache->headers[shaderIndex].index
+ << "size" << cache->headers[shaderIndex].size
+ << "format" << cache->headers[shaderIndex].format;
+
+ // call program->programId first, since that resolves the glProgramBinaryOES symbol
+ GLuint programId = program->programId();
+ glProgramBinaryOES(programId, cache->headers[shaderIndex].format,
+ cache->data + cache->headers[shaderIndex].index,
+ cache->headers[shaderIndex].size);
+
+ return true;
+}
+
+/* Stores the shader program in the cache. Returns false if there's an error with the cache, or
+ if the cache is too small to hold the shader. */
+static bool qt_cache_shader(const QOpenGLShaderProgram *shader, QOpenGLContext *ctx, const QByteArray &md5Sum)
+{
+ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
+ if (!shm || !shm->isAttached())
+ return false;
+
+ void *data = shm->data();
+ Q_ASSERT(data);
+
+ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
+
+ ShaderCacheLocker locker(shm);
+ if (!locker.isLocked())
+ return false;
+
+ int cacheIdx = cache->shaderCount;
+ if (cacheIdx >= ShaderCacheMaxEntries) {
+ traceCacheOverflow("Qt OpenGL shader cache index overflow!");
+ return false;
+ }
+
+ // now that we have the lock on the shared memory, make sure no one
+ // inserted the shader already while we were unlocked
+ if (qt_cache_index_unlocked(md5Sum, cache) != -1)
+ return true; // already cached
+
+ shaderCacheDebug() << "Caching shader at index" << cacheIdx;
+
+ GLint binaryLength = 0;
+ glGetProgramiv(shader->programId(), GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength);
+
+ if (!binaryLength) {
+ shaderCacheDebug() << "Unable to determine binary shader size!";
+ return false;
+ }
+
+ if (binaryLength > cache->availableSize()) {
+ traceCacheOverflow("Qt OpenGL shader cache data overflow!");
+ return false;
+ }
+
+ GLsizei size = 0;
+ GLenum format = 0;
+ glGetProgramBinaryOES(shader->programId(), binaryLength, &size, &format,
+ cache->data + cache->dataSize);
+
+ if (!size) {
+ shaderCacheDebug() << "Unable to get binary shader!";
+ return false;
+ }
+
+ cache->headers[cacheIdx].index = cache->dataSize;
+ cache->dataSize += binaryLength;
+ ++cache->shaderCount;
+ cache->headers[cacheIdx].size = binaryLength;
+ cache->headers[cacheIdx].format = format;
+
+ memcpy(cache->headers[cacheIdx].md5Sum, md5Sum.constData(), 16);
+
+ shaderCacheDebug() << "cached shader size" << size
+ << "format" << format
+ << "binarySize" << binaryLength
+ << "cache index" << cacheIdx
+ << "data index" << cache->headers[cacheIdx].index;
+
+ return true;
+}
+
+} // namespace
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class CachedShader
+{
+public:
+ CachedShader(const QByteArray &fragSource, const QByteArray &vertexSource)
+ : cacheIdx(-1)
+ {
+ QCryptographicHash md5Hash(QCryptographicHash::Md5);
+
+ md5Hash.addData(fragSource);
+ md5Hash.addData(vertexSource);
+
+ md5Sum = md5Hash.result();
+ }
+
+ bool isCached()
+ {
+ return cacheIndex() != -1;
+ }
+
+ int cacheIndex()
+ {
+ if (cacheIdx != -1)
+ return cacheIdx;
+ cacheIdx = qt_cache_index(md5Sum);
+ return cacheIdx;
+ }
+
+ bool load(QOpenGLShaderProgram *program, QOpenGLContext *ctx)
+ {
+ if (cacheIndex() == -1)
+ return false;
+ return qt_cached_shader(program, ctx, cacheIdx);
+ }
+
+ bool store(QOpenGLShaderProgram *program, QOpenGLContext *ctx)
+ {
+ return qt_cache_shader(program, ctx, md5Sum);
+ }
+
+private:
+ QByteArray md5Sum;
+ int cacheIdx;
+};
+
+
+QT_END_NAMESPACE
+
+#endif
+
+QT_END_HEADER
+
+#endif
+#endif
diff --git a/src/opengl/util/meego/main.cpp b/src/gui/opengl/qopenglshadercache_p.h
index 21ac5fd629..05a058050c 100644
--- a/src/opengl/util/meego/main.cpp
+++ b/src/gui/opengl/qopenglshadercache_p.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
@@ -39,51 +39,60 @@
**
****************************************************************************/
-#include <QtCore/qdebug.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.
+//
-#define QT_DEBUG_SHADER_CACHE
-#define QT_MEEGO_EXPERIMENTAL_SHADERCACHE
-#define QT_OPENGL_ES_2
-#define QT_BOOTSTRAPPED
+#ifndef QOPENGLSHADERCACHE_P_H
+#define QOPENGLSHADERCACHE_P_H
-typedef int GLsizei;
-typedef unsigned int GLenum;
+#include <QtCore/qglobal.h>
-#include "../../gl2paintengineex/qglshadercache_meego_p.h"
+#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2)
+# include "qopenglshadercache_meego_p.h"
+#else
-#include <stdlib.h>
-#include <stdio.h>
+QT_BEGIN_HEADER
-int main()
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QOpenGLShaderProgram;
+class QOpenGLContext;
+
+class CachedShader
{
- ShaderCacheSharedMemory shm;
+public:
+ inline CachedShader(const QByteArray &, const QByteArray &)
+ {}
- if (!shm.isAttached()) {
- fprintf(stderr, "Unable to attach to shared memory\n");
- return EXIT_FAILURE;
+ inline bool isCached()
+ {
+ return false;
}
- ShaderCacheLocker locker(&shm);
- if (!locker.isLocked()) {
- fprintf(stderr, "Unable to lock shared memory\n");
- return EXIT_FAILURE;
+ inline bool load(QOpenGLShaderProgram *, QOpenGLContext *)
+ {
+ return false;
}
- void *data = shm.data();
- Q_ASSERT(data);
-
- CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
-
- for (int i = 0; i < cache->shaderCount; ++i) {
- printf("Shader %d: %d bytes\n", i, cache->headers[i].size);
+ inline bool store(QOpenGLShaderProgram *, QOpenGLContext *)
+ {
+ return false;
}
+};
- printf("\nSummary:\n\n"
- " Amount of cached shaders: %d\n"
- " Bytes used: %d\n"
- " Bytes available: %d\n",
- cache->shaderCount, cache->dataSize, cache->availableSize());
+QT_END_NAMESPACE
- return EXIT_SUCCESS;
-}
+QT_END_HEADER
+#endif
+#endif
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
new file mode 100644
index 0000000000..a36982162a
--- /dev/null
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -0,0 +1,3171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglshaderprogram.h"
+#include "qopenglfunctions.h"
+#include "private/qopenglcontext_p.h"
+#include <QtCore/private/qobject_p.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QOpenGLShaderProgram
+ \brief The QOpenGLShaderProgram class allows OpenGL shader programs to be linked and used.
+ \since 5.0
+ \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).
+
+ QOpenGLShader and QOpenGLShaderProgram 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 QOpenGLContext by calling
+ QOpenGLShaderProgram::bind():
+
+ \snippet doc/src/snippets/code/src_opengl_qopenglshaderprogram.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 QOpenGLShaderProgram 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 doc/src/snippets/code/src_opengl_qopenglshaderprogram.cpp 1
+
+ With the above shader program active, we can draw a green triangle
+ as follows:
+
+ \snippet doc/src/snippets/code/src_opengl_qopenglshaderprogram.cpp 2
+
+ \section1 Binary shaders and programs
+
+ Binary shaders may be specified using \c{glShaderBinary()} on
+ the return value from QOpenGLShader::shaderId(). The QOpenGLShader 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.
+
+ \sa QOpenGLShader
+*/
+
+/*!
+ \class QOpenGLShader
+ \brief The QOpenGLShader class allows OpenGL shaders to be compiled.
+ \since 4.6
+ \ingroup painting-3D
+
+ This class supports shaders written in the OpenGL Shading Language (GLSL)
+ and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QOpenGLShader and QOpenGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ \sa QOpenGLShaderProgram
+*/
+
+/*!
+ \enum QOpenGLShader::ShaderTypeBit
+ This enum specifies the type of QOpenGLShader 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 QOpenGLShaderPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLShader)
+public:
+ QOpenGLShaderPrivate(QOpenGLContext *ctx, QOpenGLShader::ShaderType type)
+ : shaderGuard(0)
+ , shaderType(type)
+ , compiled(false)
+ , glfuncs(new QOpenGLFunctions(ctx))
+ {
+ }
+ ~QOpenGLShaderPrivate();
+
+ QOpenGLSharedResourceGuard *shaderGuard;
+ QOpenGLShader::ShaderType shaderType;
+ bool compiled;
+ QString log;
+
+ QOpenGLFunctions *glfuncs;
+
+ bool create();
+ bool compile(QOpenGLShader *q);
+ void deleteShader();
+};
+
+namespace {
+ void freeShaderFunc(QOpenGLFunctions *funcs, GLuint id)
+ {
+ funcs->glDeleteShader(id);
+ }
+}
+
+QOpenGLShaderPrivate::~QOpenGLShaderPrivate()
+{
+ delete glfuncs;
+ if (shaderGuard)
+ shaderGuard->free();
+}
+
+bool QOpenGLShaderPrivate::create()
+{
+ QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ if (!context)
+ return false;
+ GLuint shader;
+ if (shaderType == QOpenGLShader::Vertex)
+ shader = glfuncs->glCreateShader(GL_VERTEX_SHADER);
+#if 0
+ else if (shaderType == QOpenGLShader::Geometry)
+ shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER_EXT);
+#endif
+ else
+ shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER);
+ if (!shader) {
+ qWarning() << "QOpenGLShader: could not create shader";
+ return false;
+ }
+ shaderGuard = new QOpenGLSharedResourceGuard(context, shader, freeShaderFunc);
+ return true;
+}
+
+bool QOpenGLShaderPrivate::compile(QOpenGLShader *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 == QOpenGLShader::Fragment)
+ type = types[0];
+ else if (shaderType == QOpenGLShader::Vertex)
+ type = types[1];
+ else if (shaderType == QOpenGLShader::Geometry)
+ type = types[2];
+
+ if (name.isEmpty())
+ qWarning("QOpenGLShader::compile(%s): %s", type, qPrintable(log));
+ else
+ qWarning("QOpenGLShader::compile(%s)[%s]: %s", type, qPrintable(name), qPrintable(log));
+
+ delete [] logbuf;
+ }
+ return compiled;
+}
+
+void QOpenGLShaderPrivate::deleteShader()
+{
+ if (shaderGuard) {
+ shaderGuard->free();
+ shaderGuard = 0;
+ }
+}
+
+/*!
+ Constructs a new QOpenGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ QOpenGLShaderProgram::hasOpenGLShaderPrograms() will return false.
+
+ This constructor is normally followed by a call to compileSourceCode()
+ or compileSourceFile().
+
+ The shader will be associated with the current QOpenGLContext.
+
+ \sa compileSourceCode(), compileSourceFile()
+*/
+QOpenGLShader::QOpenGLShader(QOpenGLShader::ShaderType type, QObject *parent)
+ : QObject(*new QOpenGLShaderPrivate(QOpenGLContext::currentContext(), type), parent)
+{
+ Q_D(QOpenGLShader);
+ d->create();
+}
+
+/*!
+ Deletes this shader. If the shader has been attached to a
+ QOpenGLShaderProgram object, then the actual shader will stay around
+ until the QOpenGLShaderProgram is destroyed.
+*/
+QOpenGLShader::~QOpenGLShader()
+{
+}
+
+/*!
+ Returns the type of this shader.
+*/
+QOpenGLShader::ShaderType QOpenGLShader::shaderType() const
+{
+ Q_D(const QOpenGLShader);
+ 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 QOpenGL_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 QOpenGL_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 true if the source was successfully compiled, false otherwise.
+
+ \sa compileSourceFile()
+*/
+bool QOpenGLShader::compileSourceCode(const char *source)
+{
+ Q_D(QOpenGLShader);
+ 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 QOpenGL_DEFINE_QUALIFIERS
+ src.append(qualifierDefines);
+ srclen.append(GLint(sizeof(qualifierDefines) - 1));
+#endif
+#ifdef QOpenGL_REDEFINE_HIGHP
+ if (d->shaderType == Fragment) {
+ 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 true if the source was successfully compiled, false otherwise.
+
+ \sa compileSourceFile()
+*/
+bool QOpenGLShader::compileSourceCode(const QByteArray& source)
+{
+ return compileSourceCode(source.constData());
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ \sa compileSourceFile()
+*/
+bool QOpenGLShader::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 true if the file could be opened and the
+ source compiled, false otherwise.
+
+ \sa compileSourceCode()
+*/
+bool QOpenGLShader::compileSourceFile(const QString& fileName)
+{
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "QOpenGLShader: 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 QOpenGLShader::sourceCode() const
+{
+ Q_D(const QOpenGLShader);
+ 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 true if this shader has been compiled; false otherwise.
+
+ \sa compileSourceCode(), compileSourceFile()
+*/
+bool QOpenGLShader::isCompiled() const
+{
+ Q_D(const QOpenGLShader);
+ return d->compiled;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last compile.
+
+ \sa compileSourceCode(), compileSourceFile()
+*/
+QString QOpenGLShader::log() const
+{
+ Q_D(const QOpenGLShader);
+ return d->log;
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader.
+
+ \sa QOpenGLShaderProgram::programId()
+*/
+GLuint QOpenGLShader::shaderId() const
+{
+ Q_D(const QOpenGLShader);
+ return d->shaderGuard ? d->shaderGuard->id() : 0;
+}
+
+class QOpenGLShaderProgramPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLShaderProgram)
+public:
+ QOpenGLShaderProgramPrivate(QOpenGLContext *ctx)
+ : programGuard(0)
+ , linked(false)
+ , inited(false)
+ , removingShaders(false)
+ , geometryVertexCount(64)
+ , geometryInputType(0)
+ , geometryOutputType(0)
+ , glfuncs(new QOpenGLFunctions(ctx))
+ {
+ }
+ ~QOpenGLShaderProgramPrivate();
+
+ QOpenGLSharedResourceGuard *programGuard;
+ bool linked;
+ bool inited;
+ bool removingShaders;
+
+ int geometryVertexCount;
+ GLenum geometryInputType;
+ GLenum geometryOutputType;
+
+ QString log;
+ QList<QOpenGLShader *> shaders;
+ QList<QOpenGLShader *> anonShaders;
+
+ QOpenGLFunctions *glfuncs;
+
+ bool hasShader(QOpenGLShader::ShaderType type) const;
+};
+
+namespace {
+ void freeProgramFunc(QOpenGLFunctions *funcs, GLuint id)
+ {
+ funcs->glDeleteProgram(id);
+ }
+}
+
+
+QOpenGLShaderProgramPrivate::~QOpenGLShaderProgramPrivate()
+{
+ delete glfuncs;
+ if (programGuard)
+ programGuard->free();
+}
+
+bool QOpenGLShaderProgramPrivate::hasShader(QOpenGLShader::ShaderType type) const
+{
+ foreach (QOpenGLShader *shader, shaders) {
+ if (shader->shaderType() == type)
+ return true;
+ }
+ return false;
+}
+
+/*!
+ 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 QOpenGLContext.
+
+ \sa addShader()
+*/
+QOpenGLShaderProgram::QOpenGLShaderProgram(QObject *parent)
+ : QObject(*new QOpenGLShaderProgramPrivate(QOpenGLContext::currentContext()), parent)
+{
+}
+
+/*!
+ Deletes this shader program.
+*/
+QOpenGLShaderProgram::~QOpenGLShaderProgram()
+{
+}
+
+bool QOpenGLShaderProgram::init()
+{
+ Q_D(QOpenGLShaderProgram);
+ if ((d->programGuard && d->programGuard->id()) || d->inited)
+ return true;
+ d->inited = true;
+ QOpenGLContext *context = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
+ if (!context)
+ return false;
+ GLuint program = d->glfuncs->glCreateProgram();
+ if (!program) {
+ qWarning() << "QOpenGLShaderProgram: could not create shader program";
+ return false;
+ }
+ if (d->programGuard)
+ delete d->programGuard;
+ d->programGuard = new QOpenGLSharedResourceGuard(context, program, freeProgramFunc);
+ return true;
+}
+
+/*!
+ Adds a compiled \a shader to this shader program. Returns 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 QOpenGLShaderProgram instance
+ is deleted. This allows the caller to add the same shader
+ to multiple shader programs.
+
+ \sa addShaderFromSourceCode(), addShaderFromSourceFile()
+ \sa removeShader(), link(), removeAllShaders()
+*/
+bool QOpenGLShaderProgram::addShader(QOpenGLShader *shader)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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("QOpenGLShaderProgram::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 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 QOpenGLShader first.
+
+ \sa addShader(), addShaderFromSourceFile()
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::ShaderType type, const char *source)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ QOpenGLShader *shader = new QOpenGLShader(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 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 QOpenGLShader first.
+
+ \sa addShader(), addShaderFromSourceFile()
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::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 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 QOpenGLShader first.
+
+ \sa addShader(), addShaderFromSourceFile()
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QOpenGLShaderProgram::addShaderFromSourceCode(QOpenGLShader::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 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 QOpenGLShader first.
+
+ \sa addShader(), addShaderFromSourceCode()
+*/
+bool QOpenGLShaderProgram::addShaderFromSourceFile
+ (QOpenGLShader::ShaderType type, const QString& fileName)
+{
+ Q_D(QOpenGLShaderProgram);
+ if (!init())
+ return false;
+ QOpenGLShader *shader = new QOpenGLShader(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 QOpenGLContext.
+
+ \sa addShader(), link(), removeAllShaders()
+*/
+void QOpenGLShaderProgram::removeShader(QOpenGLShader *shader)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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<QOpenGLShader *> QOpenGLShaderProgram::shaders() const
+{
+ Q_D(const QOpenGLShaderProgram);
+ return d->shaders;
+}
+
+/*!
+ Removes all of the shaders that were added to this program previously.
+ The QOpenGLShader objects for the shaders will not be deleted if they
+ were constructed externally. QOpenGLShader objects that are constructed
+ internally by QOpenGLShaderProgram will be deleted.
+
+ \sa addShader(), removeShader()
+*/
+void QOpenGLShaderProgram::removeAllShaders()
+{
+ Q_D(QOpenGLShaderProgram);
+ d->removingShaders = true;
+ foreach (QOpenGLShader *shader, d->shaders) {
+ if (d->programGuard && d->programGuard->id()
+ && shader && shader->d_func()->shaderGuard)
+ {
+ d->glfuncs->glDetachShader(d->programGuard->id(), shader->d_func()->shaderGuard->id());
+ }
+ }
+ foreach (QOpenGLShader *shader, d->anonShaders) {
+ // Delete shader objects that were created anonymously.
+ delete shader;
+ }
+ 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 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 QOpenGLShaderProgram::link()
+{
+ Q_D(QOpenGLShaderProgram);
+ 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;
+ }
+
+ // Set up the geometry shader parameters
+#if 0
+ if (glProgramParameteriEXT) {
+ foreach (QOpenGLShader *shader, d->shaders) {
+ if (shader->shaderType() & QOpenGLShader::Geometry) {
+ glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT,
+ d->geometryInputType);
+ glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
+ d->geometryOutputType);
+ glProgramParameteriEXT(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 (name.isEmpty())
+ qWarning() << "QOpenGLShader::link:" << d->log;
+ else
+ qWarning() << "QOpenGLShader::link[" << name << "]:" << d->log;
+ delete [] logbuf;
+ }
+ return d->linked;
+}
+
+/*!
+ Returns true if this shader program has been linked; false otherwise.
+
+ \sa link()
+*/
+bool QOpenGLShaderProgram::isLinked() const
+{
+ Q_D(const QOpenGLShaderProgram);
+ return d->linked;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last link()
+ or addShader() with explicitly specified source code.
+
+ \sa link()
+*/
+QString QOpenGLShaderProgram::log() const
+{
+ Q_D(const QOpenGLShaderProgram);
+ return d->log;
+}
+
+/*!
+ Binds this shader program to the active QOpenGLContext and makes
+ it the current shader program. Any previously bound shader program
+ is released. This is equivalent to calling \c{glUseProgram()} on
+ programId(). Returns 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 QOpenGLShaderProgram::bind()
+{
+ Q_D(QOpenGLShaderProgram);
+ 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("QOpenGLShaderProgram::bind: program is not valid in the current context.");
+ return false;
+ }
+#endif
+ d->glfuncs->glUseProgram(program);
+ return true;
+}
+
+/*!
+ Releases the active shader program from the current QOpenGLContext.
+ This is equivalent to calling \c{glUseProgram(0)}.
+
+ \sa bind()
+*/
+void QOpenGLShaderProgram::release()
+{
+#ifndef QT_NO_DEBUG
+ Q_D(QOpenGLShaderProgram);
+ if (d->programGuard->group() != QOpenGLContextGroup::currentContextGroup())
+ qWarning("QOpenGLShaderProgram::release: program is not valid in the current context.");
+#endif
+ d->glfuncs->glUseProgram(0);
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader program.
+
+ \sa QOpenGLShader::shaderId()
+*/
+GLuint QOpenGLShaderProgram::programId() const
+{
+ Q_D(const QOpenGLShaderProgram);
+ 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<QOpenGLShaderProgram *>(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 QOpenGLShaderProgram::bindAttributeLocation(const char *name, int location)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::attributeLocation(const char *name) const
+{
+ Q_D(const QOpenGLShaderProgram);
+ if (d->linked && d->programGuard && d->programGuard->id()) {
+ return d->glfuncs->glGetAttribLocation(d->programGuard->id(), name);
+ } else {
+ qWarning() << "QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, GLfloat value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue(int location, const QColor& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeValue
+ (int location, const GLfloat *values, int columns, int rows)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ if (rows < 1 || rows > 4) {
+ qWarning() << "QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setAttributeArray
+ (int location, const GLfloat *values, int tupleSize, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::setAttributeArray
+ (int location, const QVector2D *values, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::setAttributeArray
+ (int location, const QVector3D *values, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::setAttributeArray
+ (int location, const QVector4D *values, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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.
+
+ \sa setAttributeValue(), setUniformValue(), enableAttributeArray()
+ \sa disableAttributeArray(), setAttributeBuffer()
+ \since 4.7
+*/
+void QOpenGLShaderProgram::setAttributeArray
+ (int location, GLenum type, const void *values, int tupleSize, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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.
+
+ \sa setAttributeArray()
+ \since 4.7
+*/
+void QOpenGLShaderProgram::setAttributeBuffer
+ (int location, GLenum type, int offset, int tupleSize, int stride)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ if (location != -1) {
+ d->glfuncs->glVertexAttribPointer(location, tupleSize, type, GL_TRUE, stride,
+ reinterpret_cast<const void *>(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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::enableAttributeArray(int location)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::disableAttributeArray(int location)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::uniformLocation(const char *name) const
+{
+ Q_D(const QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ if (d->linked && d->programGuard && d->programGuard->id()) {
+ return d->glfuncs->glGetUniformLocation(d->programGuard->id(), name);
+ } else {
+ qWarning() << "QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, GLfloat value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, GLint value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, GLuint value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QVector2D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QVector3D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QVector4D& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QColor& color)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QPoint& point)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QPointF& point)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QSize& size)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QSizeF& size)
+{
+ Q_D(QOpenGLShaderProgram);
+ 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 QOpenGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+// We have to repack matrices from qreal to GLfloat.
+#define setUniformMatrix(func,location,value,cols,rows) \
+ if (location == -1) \
+ return; \
+ if (sizeof(qreal) == sizeof(GLfloat)) { \
+ func(location, 1, GL_FALSE, \
+ reinterpret_cast<const GLfloat *>(value.constData())); \
+ } else { \
+ GLfloat mat[cols * rows]; \
+ const qreal *data = value.constData(); \
+ for (int i = 0; i < cols * rows; ++i) \
+ mat[i] = data[i]; \
+ func(location, 1, GL_FALSE, mat); \
+ }
+#define setUniformGenericMatrix(colfunc,location,value,cols,rows) \
+ if (location == -1) \
+ return; \
+ if (sizeof(qreal) == sizeof(GLfloat)) { \
+ const GLfloat *data = reinterpret_cast<const GLfloat *> \
+ (value.constData()); \
+ colfunc(location, cols, data); \
+ } else { \
+ GLfloat mat[cols * rows]; \
+ const qreal *data = value.constData(); \
+ for (int i = 0; i < cols * rows; ++i) \
+ mat[i] = data[i]; \
+ colfunc(location, cols, mat); \
+ }
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformMatrix(d->glfuncs->glUniformMatrix2fv, location, value, 2, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform3fv, location, value, 2, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform4fv, location, value, 2, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform2fv, location, value, 3, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformMatrix(d->glfuncs->glUniformMatrix3fv, location, value, 3, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform4fv, location, value, 3, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform2fv, location, value, 4, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformGenericMatrix
+ (d->glfuncs->glUniform3fv, location, value, 4, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::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 QOpenGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
+{
+ Q_D(QOpenGLShaderProgram);
+ Q_UNUSED(d);
+ setUniformMatrix(d->glfuncs->glUniformMatrix4fv, location, value, 4, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QOpenGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ \overload
+
+ Sets t