remove the opengl component

Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
Ivailo Monev 2016-11-16 13:53:20 +00:00
parent 8c8cfc8f83
commit 71ffb62f31
171 changed files with 87 additions and 61262 deletions

View file

@ -123,12 +123,6 @@ add_feature_info(gtk2 WITH_GTK2 "an open source something")
option(WITH_GCONF2 "Build gconf2 support" ON)
add_feature_info(gconf2 WITH_GCONF2 "an open source something")
option(WITH_EGL "Build egl support" OFF)
add_feature_info(egl WITH_EGL "an open source something")
option(WITH_OPENGL "Build opengl support" ON)
add_feature_info(opengl WITH_OPENGL "an open source something")
option(WITH_FREETYPE "Build freetype2 support" ON)
add_feature_info(freetype2 WITH_FREETYPE "an open source something")
@ -173,12 +167,6 @@ add_feature_info(utils KATIE_UTILS "developers build option")
option(KATIE_ALLINONE "Build targets from single source file" OFF)
add_feature_info(allinone KATIE_ALLINONE "experimental build option")
option(WITH_OPENGLES1 "Build opengles1 support" OFF)
add_feature_info(opengles1 WITH_OPENGLES1 "an open source something")
option(WITH_OPENGLES2 "Build opengles2 support" OFF)
add_feature_info(opengles2 WITH_OPENGLES2 "an open source something")
option(WITH_ACCESSIBILITY "Build accessibility support" ON)
add_feature_info(accessibility WITH_ACCESSIBILITY "an open source something")
@ -397,22 +385,6 @@ set_package_properties(GConf2 PROPERTIES
TYPE RECOMMENDED
)
find_package(EGL)
set_package_properties(EGL PROPERTIES
PURPOSE "Required for EGL support"
DESCRIPTION "Platform dependent EGL implementation"
URL ""
TYPE RECOMMENDED
)
find_package(OpenGL)
set_package_properties(OpenGL PROPERTIES
PURPOSE "Required for GL/EGL support"
DESCRIPTION "Platform dependent OpenGL implementation"
URL ""
TYPE RECOMMENDED
)
find_package(ODBC)
set_package_properties(ODBC PROPERTIES
PURPOSE "Required for ODBC database support"
@ -502,21 +474,11 @@ if(ENABLE_TESTING)
add_definitions(-DQT_BUILD_INTERNAL)
endif()
if(WITH_OPENGLES1 OR WITH_OPENGLES2 AND NOT WITH_EGL)
message(FATAL_ERROR "\nOpenGLES requires EGL")
elseif(NOT (WITH_OPENGLES1 OR WITH_OPENGLES2) AND WITH_EGL)
message(FATAL_ERROR "\nEGL requires OpenGLES")
endif()
# optional packages
if(NOT WITH_THREADS OR NOT THREADS_FOUND)
katie_definition(-DQT_NO_THREAD)
endif()
if(NOT WITH_EGL OR NOT EGL_FOUND)
katie_definition(-DQT_NO_EGL)
endif()
if(NOT WITH_FREETYPE OR NOT FREETYPE_FOUND)
set(WITH_FONTCONFIG OFF)
katie_definition(-DQT_NO_FREETYPE)
@ -545,12 +507,6 @@ if(NOT WITH_NIS OR NOT NIS_FOUND)
katie_definition(-DQT_NO_NIS)
endif()
if(NOT WITH_OPENGL OR NOT OPENGL_FOUND)
katie_definition(-DQT_NO_OPENGL)
else()
set(KATIE_COMPONENTS "${KATIE_COMPONENTS} OpenGL")
endif()
if(NOT WITH_PNG OR NOT PNG_FOUND)
katie_definition(-DQT_NO_IMAGEFORMAT_PNG)
endif()
@ -584,14 +540,6 @@ if(NOT WITH_ACCESSIBILITY)
katie_definition(-DQT_NO_ACCESSIBILITY)
endif()
if(WITH_OPENGLES1)
katie_definition(-DQT_OPENGL_ES_1 -DQT_OPENGL_ES)
endif()
if(WITH_OPENGLES2)
katie_definition(-DQT_OPENGL_ES_2 -DQT_OPENGL_ES)
endif()
# optional packages with interface definition only for convenience
if(NOT WITH_ICONV OR NOT ICONV_FOUND)
katie_definition(-DQT_NO_ICONV)
@ -642,9 +590,6 @@ if(NOT KATIE_BOOTSTRAP)
add_subdirectory(src/gui)
add_subdirectory(src/imports)
add_subdirectory(src/network)
if(WITH_OPENGL AND OPENGL_FOUND)
add_subdirectory(src/opengl)
endif()
add_subdirectory(src/plugins)
add_subdirectory(src/script)
add_subdirectory(src/scripttools)
@ -935,9 +880,6 @@ katie_generate_obsolete(qnetworkconfigurationmanager.h QtNetwork qnetworkconfigm
katie_generate_obsolete(qnetworkproxyfactory.h QtNetwork qnetworkproxy.h)
katie_generate_obsolete(qhttppart.h QtNetwork qhttpmultipart.h)
katie_generate_obsolete(qhttpheader.h QtNetwork qhttp.h)
katie_generate_obsolete(qglshader.h QtOpenGL qglshaderprogram.h)
katie_generate_obsolete(qglcontext.h QtOpenGL qgl.h)
katie_generate_obsolete(qglwidget.h QtOpenGL qgl.h)
katie_generate_obsolete(qtestaccessibility.h QtTest qtestaccessible.h)
katie_generate_obsolete(qeventsizeofchecker.h QtTest qtestspontaneevent.h)
katie_generate_obsolete(qtestkeyclicksevent.h QtTest qtestevent.h)

2
README
View file

@ -7,7 +7,7 @@ There are several things you should be aware before considering Katie:
- some components and tools have been removed:
- QMake, Linguist, Assistant, checksdk, macdeployqt, pixeltool, qconfig,
qdoc, qev, qvfb, runonphone and other non-essential
- Qt3Support, QtWebKit, QtHelp, QtXmlPatterns, ActiveQt, Phonon and
- Qt3Support, QtWebKit, QtHelp, QtXmlPatterns, QtOpenGL, ActiveQt, Phonon and
QtMultimedia
- some things have changed:

View file

@ -229,11 +229,6 @@ incmap = {
'QDBusSignature': 'qdbusextratypes.h',
'QDBusVariant': 'qdbusextratypes.h',
},
'QtOpenGL': {
'QGLWidget': 'qgl.h',
'QGLContext': 'qgl.h',
'QGLShader': 'qglshaderprogram.h',
},
'QtXml': {
'QDomAttr': 'qdom.h',
'QDomDocument': 'qdom.h',

View file

@ -85,6 +85,8 @@
#define QT_NO_XIM
#define QT_NO_IM
#define QT_NO_SOUND
#define QT_NO_EGL
#define QT_NO_OPENGL
/* Qt build specs */
#ifndef QT_EDITION
@ -147,7 +149,6 @@
#cmakedefine QT_NO_DYNAMIC_CAST
#cmakedefine QT_NO_DYNAMIC_LIBRARY
#cmakedefine QT_NO_EFFECTS
#cmakedefine QT_NO_EGL
#cmakedefine QT_NO_EMIT
#cmakedefine QT_NO_ERRORMESSAGE
#cmakedefine QT_NO_EXCEPTIONS

View file

@ -342,57 +342,55 @@ public:
WA_WindowPropagation = 58,
WA_NoX11EventCompression = 59,
WA_TintedBackground = 60,
WA_X11OpenGLOverlay = 61,
WA_AlwaysShowToolTips = 62,
WA_SetStyle = 63,
WA_TintedBackground = 59,
WA_AlwaysShowToolTips = 60,
WA_SetStyle = 61,
WA_SetLocale = 64,
WA_SetLocale = 62,
WA_LayoutUsesWidgetRect = 65,
WA_StyledBackground = 66, // internal
WA_CanHostQMdiSubWindowTitleBar = 67, // Internal
WA_LayoutUsesWidgetRect = 63,
WA_StyledBackground = 64, // internal
WA_CanHostQMdiSubWindowTitleBar = 65, // Internal
WA_StyleSheet = 68, // internal
WA_StyleSheet = 66, // internal
WA_ShowWithoutActivating = 69,
WA_ShowWithoutActivating = 67,
WA_X11BypassTransientForHint = 70,
WA_X11BypassTransientForHint = 68,
WA_NativeWindow = 71,
WA_DontCreateNativeAncestors = 72,
WA_NativeWindow = 69,
WA_DontCreateNativeAncestors = 70,
WA_DontShowOnScreen = 73,
WA_DontShowOnScreen = 71,
// window types from http://standards.freedesktop.org/wm-spec/
WA_X11NetWmWindowTypeDesktop = 74,
WA_X11NetWmWindowTypeDock = 75,
WA_X11NetWmWindowTypeToolBar = 76,
WA_X11NetWmWindowTypeMenu = 77,
WA_X11NetWmWindowTypeUtility = 78,
WA_X11NetWmWindowTypeSplash = 79,
WA_X11NetWmWindowTypeDialog = 80,
WA_X11NetWmWindowTypeDropDownMenu = 81,
WA_X11NetWmWindowTypePopupMenu = 82,
WA_X11NetWmWindowTypeToolTip = 83,
WA_X11NetWmWindowTypeNotification = 84,
WA_X11NetWmWindowTypeCombo = 85,
WA_X11NetWmWindowTypeDND = 86,
WA_X11NetWmWindowTypeDesktop = 72,
WA_X11NetWmWindowTypeDock = 73,
WA_X11NetWmWindowTypeToolBar = 74,
WA_X11NetWmWindowTypeMenu = 75,
WA_X11NetWmWindowTypeUtility = 76,
WA_X11NetWmWindowTypeSplash = 77,
WA_X11NetWmWindowTypeDialog = 78,
WA_X11NetWmWindowTypeDropDownMenu = 79,
WA_X11NetWmWindowTypePopupMenu = 80,
WA_X11NetWmWindowTypeToolTip = 81,
WA_X11NetWmWindowTypeNotification = 82,
WA_X11NetWmWindowTypeCombo = 83,
WA_X11NetWmWindowTypeDND = 84,
WA_SetWindowModality = 87,
WA_WState_WindowOpacitySet = 88, // internal
WA_TranslucentBackground = 89,
WA_SetWindowModality = 85,
WA_WState_WindowOpacitySet = 86, // internal
WA_TranslucentBackground = 87,
WA_AcceptTouchEvents = 90,
WA_WState_AcceptedTouchBeginEvent = 91,
WA_TouchPadAcceptSingleTouchEvents = 92,
WA_AcceptTouchEvents = 88,
WA_WState_AcceptedTouchBeginEvent = 89,
WA_TouchPadAcceptSingleTouchEvents = 90,
WA_LockPortraitOrientation = 93,
WA_LockLandscapeOrientation = 94,
WA_AutoOrientation = 95,
WA_LockPortraitOrientation = 91,
WA_LockLandscapeOrientation = 92,
WA_AutoOrientation = 93,
WA_X11DoNotAcceptFocus = 96,
WA_X11DoNotAcceptFocus = 94,
// Add new attributes before this line
WA_AttributeCount
@ -1436,8 +1434,7 @@ public:
Pbuffer = 5, // GL pbuffer
FramebufferObject = 6, // GL framebuffer object
CustomRaster = 7,
PaintBuffer = 8,
OpenGL = 9
PaintBuffer = 8
};
enum RelayoutType {
RelayoutNormal,

View file

@ -1109,9 +1109,7 @@
\omitvalue WA_DontShowOnScreen
\omitvalue WA_InvalidSize
\omitvalue WA_ForceUpdatesDisabled
\omitvalue WA_NoX11EventCompression
\omitvalue WA_TintedBackground
\omitvalue WA_X11OpenGLOverlay
\omitvalue WA_CanHostQMdiSubWindowTitleBar
\omitvalue WA_AttributeCount
\omitvalue WA_StyleSheet

View file

@ -340,11 +340,7 @@ void QDeclarativeTextLayout::draw(QPainter *painter, const QPointF &p)
{
QPainterPrivate *priv = QPainterPrivate::get(painter);
bool paintEngineSupportsTransformations = priv->extended &&
(priv->extended->type() == QPaintEngine::OpenGL2 ||
priv->extended->type() == QPaintEngine::OpenGL);
if (!paintEngineSupportsTransformations || !priv->state->matrix.isAffine()) {
if (!priv->state->matrix.isAffine()) {
QTextLayout::draw(painter, p);
return;
}

View file

@ -392,7 +392,6 @@ include(accessible/accessible.cmake)
include(animation/animation.cmake)
include(dialogs/dialogs.cmake)
include(effects/effects.cmake)
include(egl/egl.cmake)
include(graphicsview/graphicsview.cmake)
include(image/image.cmake)
include(itemviews/itemviews.cmake)
@ -415,7 +414,6 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/animation
${CMAKE_CURRENT_SOURCE_DIR}/dialogs
${CMAKE_CURRENT_SOURCE_DIR}/effects
${CMAKE_CURRENT_SOURCE_DIR}/egl
${CMAKE_CURRENT_SOURCE_DIR}/graphicsview
${CMAKE_CURRENT_SOURCE_DIR}/image
${CMAKE_CURRENT_SOURCE_DIR}/itemviews
@ -431,7 +429,6 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}/animation
${CMAKE_CURRENT_BINARY_DIR}/dialogs
${CMAKE_CURRENT_BINARY_DIR}/effects
${CMAKE_CURRENT_BINARY_DIR}/egl
${CMAKE_CURRENT_BINARY_DIR}/graphicsview
${CMAKE_CURRENT_BINARY_DIR}/image
${CMAKE_CURRENT_BINARY_DIR}/itemviews

View file

@ -860,12 +860,8 @@ void QGraphicsBlurEffect::draw(QPainter *painter)
return;
}
PixmapPadMode mode = PadToEffectiveBoundingRect;
if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
mode = NoPad;
QPoint offset;
QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, mode);
QPixmap pixmap = sourcePixmap(Qt::LogicalCoordinates, &offset, PadToEffectiveBoundingRect);
if (pixmap.isNull())
return;
@ -1052,13 +1048,9 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter)
return;
}
PixmapPadMode mode = PadToEffectiveBoundingRect;
if (painter->paintEngine()->type() == QPaintEngine::OpenGL2)
mode = NoPad;
// Draw pixmap in device coordinates to avoid pixmap scaling.
QPoint offset;
const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, mode);
const QPixmap pixmap = sourcePixmap(Qt::DeviceCoordinates, &offset, PadToEffectiveBoundingRect);
if (pixmap.isNull())
return;

View file

@ -1,20 +0,0 @@
if(WITH_EGL AND EGL_FOUND)
set(GUI_HEADERS
${GUI_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/egl/qegl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/egl/qeglcontext_p.h
${CMAKE_CURRENT_SOURCE_DIR}/egl/qeglproperties_p.h
)
set(GUI_SOURCES
${GUI_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/egl/qegl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/egl/qeglproperties.cpp
${CMAKE_CURRENT_SOURCE_DIR}/egl/qegl_x11.cpp
)
set(EXTRA_GUI_LIBS
${EXTRA_GUI_LIBS}
${EGL_LIBRARIES}
)
include_directories(${EGL_INCLUDES})
endif()

View file

@ -1,703 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
#include <QtCore/qatomic.h>
#include <QtCore/qdebug.h>
#include "qegl_p.h"
#include "qeglcontext_p.h"
QT_BEGIN_NAMESPACE
/*
QEglContextTracker is used to track the EGL contexts that we
create internally in Qt, so that we can call eglTerminate() to
free additional EGL resources when the last context is destroyed.
*/
class QEglContextTracker
{
public:
static void ref() { contexts.ref(); }
static void deref() {
if (!contexts.deref()) {
eglTerminate(QEgl::display());
displayOpen = 0;
}
}
static void setDisplayOpened() { displayOpen = 1; }
static bool displayOpened() { return displayOpen; }
private:
static QAtomicInt contexts;
static QAtomicInt displayOpen;
};
QAtomicInt QEglContextTracker::contexts = QAtomicInt(0);
QAtomicInt QEglContextTracker::displayOpen = QAtomicInt(0);
// Current GL and VG contexts. These are used to determine if
// we can avoid an eglMakeCurrent() after a call to lazyDoneCurrent().
// If a background thread modifies the value, the worst that will
// happen is a redundant eglMakeCurrent() in the foreground thread.
static QEglContext * volatile currentGLContext = 0;
static QEglContext * volatile currentVGContext = 0;
QEglContext::QEglContext()
: apiType(QEgl::OpenGL)
, ctx(EGL_NO_CONTEXT)
, cfg(QEGL_NO_CONFIG)
, currentSurface(EGL_NO_SURFACE)
, current(false)
, ownsContext(true)
, sharing(false)
, apiChanged(false)
{
QEglContextTracker::ref();
}
QEglContext::~QEglContext()
{
destroyContext();
if (currentGLContext == this)
currentGLContext = 0;
if (currentVGContext == this)
currentVGContext = 0;
QEglContextTracker::deref();
}
bool QEglContext::isValid() const
{
return (ctx != EGL_NO_CONTEXT);
}
bool QEglContext::isCurrent() const
{
return current;
}
EGLConfig QEgl::defaultConfig(int devType, API api, ConfigOptions options)
{
if ( (devType != QInternal::Pixmap) && ((options & Renderable) == 0))
qWarning("QEgl::defaultConfig() - Only configs for pixmaps make sense to be read-only!");
EGLConfig* targetConfig = 0;
static EGLConfig defaultGLConfigs[] = {
QEGL_NO_CONFIG, // 0 Window Renderable Translucent
QEGL_NO_CONFIG, // 1 Window Renderable Opaque
QEGL_NO_CONFIG, // 2 PBuffer Renderable Translucent
QEGL_NO_CONFIG, // 3 PBuffer Renderable Opaque
QEGL_NO_CONFIG, // 4 Pixmap Renderable Translucent
QEGL_NO_CONFIG, // 5 Pixmap Renderable Opaque
QEGL_NO_CONFIG, // 6 Pixmap ReadOnly Translucent
QEGL_NO_CONFIG // 7 Pixmap ReadOnly Opaque
};
if (api == OpenGL) {
if (devType == QInternal::Widget) {
if (options & Translucent)
targetConfig = &(defaultGLConfigs[0]);
else // Opaque
targetConfig = &(defaultGLConfigs[1]);
} else if (devType == QInternal::Pbuffer) {
if (options & Translucent)
targetConfig = &(defaultGLConfigs[2]);
else // Opaque
targetConfig = &(defaultGLConfigs[3]);
} else if (devType == QInternal::Pixmap) {
if (options & Renderable) {
if (options & Translucent)
targetConfig = &(defaultGLConfigs[4]);
else // Opaque
targetConfig = &(defaultGLConfigs[5]);
} else { // ReadOnly
if (options & Translucent)
targetConfig = &(defaultGLConfigs[6]);
else // Opaque
targetConfig = &(defaultGLConfigs[7]);
}
}
}
if (!targetConfig) {
qWarning("QEgl::defaultConfig() - No default config for device/api/options combo");
return QEGL_NO_CONFIG;
}
if (*targetConfig != QEGL_NO_CONFIG)
return *targetConfig;
// We haven't found an EGL config for the target config yet, so do it now:
// Allow overriding from an environment variable:
const QByteArray configId = qgetenv("QT_GL_EGL_CONFIG");
if (!configId.isEmpty()) {
// Overridden, so get the EGLConfig for the specified config ID:
EGLint properties[] = {
EGL_CONFIG_ID, (EGLint)configId.toInt(),
EGL_NONE
};
EGLint configCount = 0;
eglChooseConfig(display(), properties, targetConfig, 1, &configCount);
if (configCount > 0)
return *targetConfig;
qWarning() << "QEgl::defaultConfig() -" << configId << "appears to be invalid";
}
QEglProperties configAttribs;
configAttribs.setRenderableType(api);
EGLint surfaceType;
switch (devType) {
case QInternal::Widget:
surfaceType = EGL_WINDOW_BIT;
break;
case QInternal::Pixmap:
surfaceType = EGL_PIXMAP_BIT;
break;
case QInternal::Pbuffer:
surfaceType = EGL_PBUFFER_BIT;
break;
default:
qWarning("QEgl::defaultConfig() - Can't create EGL surface for %d device type", devType);
return QEGL_NO_CONFIG;
};
configAttribs.setValue(EGL_SURFACE_TYPE, surfaceType);
#ifdef EGL_BIND_TO_TEXTURE_RGBA
if (devType == QInternal::Pixmap || devType == QInternal::Pbuffer) {
if (options & Translucent)
configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
else
configAttribs.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
}
#endif
// Add paint engine requirements, OpenGL paint engine need to have
// stencil and sample buffers
configAttribs.setValue(EGL_STENCIL_SIZE, 1);
configAttribs.setValue(EGL_SAMPLE_BUFFERS, 1);
#ifndef QT_OPENGL_ES_2
// Additionally, the GL1 engine likes to have a depth buffer for clipping
configAttribs.setValue(EGL_DEPTH_SIZE, 1);
#endif
if (options & Translucent)
configAttribs.setValue(EGL_ALPHA_SIZE, 1);
*targetConfig = chooseConfig(&configAttribs, QEgl::BestPixelFormat);
return *targetConfig;
}
// Choose a configuration that matches "properties".
EGLConfig QEgl::chooseConfig(const QEglProperties* properties, QEgl::PixelFormatMatch match)
{
QEglProperties props(*properties);
EGLConfig cfg = QEGL_NO_CONFIG;
do {
// Get the number of matching configurations for this set of properties.
EGLint matching = 0;
EGLDisplay dpy = QEgl::display();
if (!eglChooseConfig(dpy, props.properties(), 0, 0, &matching) || !matching)
continue;
// If we want the best pixel format, then return the first
// matching configuration.
if (match == QEgl::BestPixelFormat) {
eglChooseConfig(display(), props.properties(), &cfg, 1, &matching);
if (matching < 1)
continue;
return cfg;
}
// Fetch all of the matching configurations and find the
// first that matches the pixel format we wanted.
EGLint size = matching;
EGLConfig *configs = new EGLConfig [size];
eglChooseConfig(display(), props.properties(), configs, size, &matching);
for (EGLint index = 0; index < size; ++index) {
EGLint red, green, blue, alpha;
eglGetConfigAttrib(display(), configs[index], EGL_RED_SIZE, &red);
eglGetConfigAttrib(display(), configs[index], EGL_GREEN_SIZE, &green);
eglGetConfigAttrib(display(), configs[index], EGL_BLUE_SIZE, &blue);
eglGetConfigAttrib(display(), configs[index], EGL_ALPHA_SIZE, &alpha);
if (red == props.value(EGL_RED_SIZE) &&
green == props.value(EGL_GREEN_SIZE) &&
blue == props.value(EGL_BLUE_SIZE) &&
(props.value(EGL_ALPHA_SIZE) == 0 ||
alpha == props.value(EGL_ALPHA_SIZE))) {
cfg = configs[index];
delete [] configs;
return cfg;
}
}
delete [] configs;
} while (props.reduceConfiguration());
#ifdef EGL_BIND_TO_TEXTURE_RGBA
// Don't report an error just yet if we failed to get a pbuffer
// configuration with texture rendering. Only report failure if
// we cannot get any pbuffer configurations at all.
if (props.value(EGL_BIND_TO_TEXTURE_RGBA) == EGL_DONT_CARE &&
props.value(EGL_BIND_TO_TEXTURE_RGB) == EGL_DONT_CARE)
#endif
{
qWarning() << "QEglContext::chooseConfig(): Could not find a suitable EGL configuration";
qWarning() << "Requested:" << props.toString();
qWarning() << "Available:";
QEgl::dumpAllConfigs();
}
return QEGL_NO_CONFIG;
}
bool QEglContext::chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match)
{
cfg = QEgl::chooseConfig(&properties, match);
return cfg != QEGL_NO_CONFIG;
}
EGLSurface QEglContext::createSurface(QPaintDevice* device, const QEglProperties *properties)
{
return QEgl::createSurface(device, cfg, properties);
}
// Create the EGLContext.
bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties *properties)
{
// We need to select the correct API before calling eglCreateContext().
#ifdef QT_OPENGL_ES
#ifdef EGL_OPENGL_ES_API
if (apiType == QEgl::OpenGL)
eglBindAPI(EGL_OPENGL_ES_API);
#endif
#else
#ifdef EGL_OPENGL_API
if (apiType == QEgl::OpenGL)
eglBindAPI(EGL_OPENGL_API);
#endif
#endif //defined(QT_OPENGL_ES)
// Create a new context for the configuration.
QEglProperties contextProps;
if (properties)
contextProps = *properties;
#ifdef QT_OPENGL_ES_2
if (apiType == QEgl::OpenGL)
contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2);
#endif
sharing = false;
if (shareContext && shareContext->ctx == EGL_NO_CONTEXT)
shareContext = 0;
if (shareContext) {
ctx = eglCreateContext(QEgl::display(), cfg, shareContext->ctx, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
qWarning() << "QEglContext::createContext(): Could not share context:" << QEgl::errorString();
shareContext = 0;
} else {
sharing = true;
}
}
if (ctx == EGL_NO_CONTEXT) {
ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties());
if (ctx == EGL_NO_CONTEXT) {
qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString();
return false;
}
}
return true;
}
// Destroy an EGL surface object. If it was current on this context
// then call doneCurrent() for it first.
void QEglContext::destroySurface(EGLSurface surface)
{
if (surface != EGL_NO_SURFACE) {
if (surface == currentSurface)
doneCurrent();
eglDestroySurface(display(), surface);
}
}
// Destroy the context. Note: this does not destroy the surface.
void QEglContext::destroyContext()
{
if (ctx != EGL_NO_CONTEXT && ownsContext)
eglDestroyContext(display(), ctx);
ctx = EGL_NO_CONTEXT;
cfg = 0;
}
bool QEglContext::makeCurrent(EGLSurface surface)
{
if (ctx == EGL_NO_CONTEXT) {
qWarning() << "QEglContext::makeCurrent(): Cannot make invalid context current";
return false;
}
if (surface == EGL_NO_SURFACE) {
qWarning() << "QEglContext::makeCurrent(): Cannot make invalid surface current";
return false;
}
// If lazyDoneCurrent() was called on the surface, then we may be able
// to assume that it is still current within the thread.
if (surface == currentSurface && currentContext(apiType) == this
&& !apiChanged) {
current = true;
return true;
}
current = true;
currentSurface = surface;
setCurrentContext(apiType, this);
// Force the right API to be bound before making the context current.
// The EGL implementation should be able to figure this out from ctx,
// but some systems require the API to be explicitly set anyway.
#ifdef EGL_OPENGL_ES_API
if (apiType == QEgl::OpenGL)
eglBindAPI(EGL_OPENGL_ES_API);
#endif
bool ok = eglMakeCurrent(QEgl::display(), surface, surface, ctx);
if (!ok)
qWarning() << "QEglContext::makeCurrent(" << surface << "):" << QEgl::errorString();
return ok;
}
bool QEglContext::doneCurrent()
{
// If the context is invalid, we assume that an error was reported
// when makeCurrent() was called.
if (ctx == EGL_NO_CONTEXT)
return false;
current = false;
currentSurface = EGL_NO_SURFACE;
setCurrentContext(apiType, 0);
// We need to select the correct API before calling eglMakeCurrent()
// with EGL_NO_CONTEXT because threads can have both OpenGL
// contexts active at the same time.
#ifdef EGL_OPENGL_ES_API
if (apiType == QEgl::OpenGL)
eglBindAPI(EGL_OPENGL_ES_API);
#endif
bool ok = eglMakeCurrent(QEgl::display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok)
qWarning() << "QEglContext::doneCurrent():" << QEgl::errorString();
return ok;
}
// Act as though doneCurrent() was called, but keep the context
// and the surface active for the moment. This allows makeCurrent()
// to skip a call to eglMakeCurrent() if we are using the same
// surface as the last set of painting operations. We leave the
// currentContext() pointer as-is for now.
bool QEglContext::lazyDoneCurrent()
{
current = false;
return true;
}
bool QEglContext::swapBuffers(EGLSurface surface)
{
if(ctx == EGL_NO_CONTEXT)
return false;
bool ok = eglSwapBuffers(QEgl::display(), surface);
if (!ok)
qWarning() << "QEglContext::swapBuffers():" << QEgl::errorString();
return ok;
}
bool QEglContext::swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region) {
QVector<QRect> qrects = region->rects();
EGLint *gl_rects;
uint count;
uint i;
count = qrects.size();
QVarLengthArray <EGLint> arr(4 * count);
gl_rects = arr.data();
for (i = 0; i < count; i++) {
QRect qrect = qrects[i];
gl_rects[4 * i + 0] = qrect.x();
gl_rects[4 * i + 1] = qrect.y();
gl_rects[4 * i + 2] = qrect.width();
gl_rects[4 * i + 3] = qrect.height();
}
bool ok = QEgl::eglSwapBuffersRegion2NOK(QEgl::display(), surface, count, gl_rects);
if (!ok)
qWarning() << "QEglContext::swapBuffersRegion2NOK():" << QEgl::errorString();
return ok;
}
int QEglContext::configAttrib(int name) const
{
EGLint value;
EGLBoolean success = eglGetConfigAttrib(QEgl::display(), cfg, name, &value);
if (success)
return value;
else
return EGL_DONT_CARE;
}
typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint*);
typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
// Defined in qegl.cpp:
static _eglCreateImageKHR qt_eglCreateImageKHR = 0;
static _eglDestroyImageKHR qt_eglDestroyImageKHR = 0;
typedef EGLBoolean (EGLAPIENTRY *_eglSwapBuffersRegion2NOK)(EGLDisplay, EGLSurface, EGLint, const EGLint*);
static _eglSwapBuffersRegion2NOK qt_eglSwapBuffersRegion2NOK = 0;
EGLDisplay QEgl::display()
{
static EGLDisplay dpy = EGL_NO_DISPLAY;
if (!QEglContextTracker::displayOpened()) {
dpy = eglGetDisplay(nativeDisplay());
QEglContextTracker::setDisplayOpened();
if (dpy == EGL_NO_DISPLAY) {
qWarning("QEgl::display(): Falling back to EGL_DEFAULT_DISPLAY");
dpy = eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY));
}
if (dpy == EGL_NO_DISPLAY) {
qWarning("QEgl::display(): Can't even open the default display");
return EGL_NO_DISPLAY;
}
if (!eglInitialize(dpy, NULL, NULL)) {
qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString();
return EGL_NO_DISPLAY;
}
// Resolve the egl extension function pointers:
#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
qt_eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
qt_eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
}
#endif
if (QEgl::hasExtension("EGL_NOK_swap_region2")) {
qt_eglSwapBuffersRegion2NOK = (_eglSwapBuffersRegion2NOK) eglGetProcAddress("eglSwapBuffersRegion2NOK");
}
}
return dpy;
}
EGLImageKHR QEgl::eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
{
if (qt_eglCreateImageKHR)
return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
QEgl::display(); // Initialises function pointers
if (qt_eglCreateImageKHR)
return qt_eglCreateImageKHR(dpy, ctx, target, buffer, attrib_list);
qWarning("QEgl::eglCreateImageKHR() called but EGL_KHR_image(_base) extension not present");
return 0;
}
EGLBoolean QEgl::eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
{
if (qt_eglDestroyImageKHR)
return qt_eglDestroyImageKHR(dpy, img);
QEgl::display(); // Initialises function pointers
if (qt_eglDestroyImageKHR)
return qt_eglDestroyImageKHR(dpy, img);
qWarning("QEgl::eglDestroyImageKHR() called but EGL_KHR_image(_base) extension not present");
return 0;
}
EGLBoolean QEgl::eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects)
{
if (qt_eglSwapBuffersRegion2NOK)
return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
QEgl::display(); // Initialises function pointers
if (qt_eglSwapBuffersRegion2NOK)
return qt_eglSwapBuffersRegion2NOK(dpy, surface, count, rects);
qWarning("QEgl::eglSwapBuffersRegion2NOK() called but EGL_NOK_swap_region2 extension not present");
return 0;
}
#ifndef Q_WS_X11
EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *properties)
{
// Create the native drawable for the paint device.
int devType = device->devType();
EGLNativePixmapType pixmapDrawable = 0;
EGLNativeWindowType windowDrawable = 0;
bool ok;
if (devType == QInternal::Pixmap) {
pixmapDrawable = nativePixmap(static_cast<QPixmap *>(device));
ok = (pixmapDrawable != 0);
} else if (devType == QInternal::Widget) {
windowDrawable = nativeWindow(static_cast<QWidget *>(device));
ok = (windowDrawable != 0);
} else {
ok = false;
}
if (!ok) {
qWarning("QEglContext::createSurface(): Cannot create the native EGL drawable");
return EGL_NO_SURFACE;
}
// Create the EGL surface to draw into, based on the native drawable.
const EGLint *props;
if (properties)
props = properties->properties();
else
props = 0;
EGLSurface surf = EGL_NO_SURFACE;
if (devType == QInternal::Widget)
surf = eglCreateWindowSurface(QEgl::display(), cfg, windowDrawable, props);
else
surf = eglCreatePixmapSurface(QEgl::display(), cfg, pixmapDrawable, props);
if (surf == EGL_NO_SURFACE) {
qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
}
return surf;
}
#endif
// Return the error string associated with a specific code.
QString QEgl::errorString(EGLint code)
{
static const char * const errors[] = {
"Success (0x3000)", // No tr
"Not initialized (0x3001)", // No tr
"Bad access (0x3002)", // No tr
"Bad alloc (0x3003)", // No tr
"Bad attribute (0x3004)", // No tr
"Bad config (0x3005)", // No tr
"Bad context (0x3006)", // No tr
"Bad current surface (0x3007)", // No tr
"Bad display (0x3008)", // No tr
"Bad match (0x3009)", // No tr
"Bad native pixmap (0x300A)", // No tr
"Bad native window (0x300B)", // No tr
"Bad parameter (0x300C)", // No tr
"Bad surface (0x300D)", // No tr
"Context lost (0x300E)" // No tr
};
if (code >= 0x3000 && code <= 0x300E) {
return QString::fromLatin1(errors[code - 0x3000]);
} else {
return QLatin1String("0x") + QString::number(int(code), 16);
}
}
// Dump all of the EGL configurations supported by the system.
void QEgl::dumpAllConfigs()
{
QEglProperties props;
EGLint count = 0;
if (!eglGetConfigs(display(), 0, 0, &count) || count < 1)
return;
EGLConfig *configs = new EGLConfig [count];
eglGetConfigs(display(), configs, count, &count);
for (EGLint index = 0; index < count; ++index) {
props = QEglProperties(configs[index]);
qWarning() << props.toString();
}
delete [] configs;
}
QString QEgl::extensions()
{
const char* exts = eglQueryString(QEgl::display(), EGL_EXTENSIONS);
return QString(QLatin1String(exts));
}
bool QEgl::hasExtension(const char* extensionName)
{
QList<QByteArray> extensions =
QByteArray(reinterpret_cast<const char *>
(eglQueryString(QEgl::display(), EGL_EXTENSIONS))).split(' ');
return extensions.contains(extensionName);
}
QEglContext *QEglContext::currentContext(QEgl::API api)
{
if (api == QEgl::OpenGL)
return currentGLContext;
else
return currentVGContext;
}
void QEglContext::setCurrentContext(QEgl::API api, QEglContext *context)
{
if (api == QEgl::OpenGL)
currentGLContext = context;
else
currentVGContext = context;
}
QT_END_NAMESPACE

View file

@ -1,207 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QEGL_P_H
#define QEGL_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 QtOpenGL modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
QT_BEGIN_INCLUDE_NAMESPACE
#if defined(Q_WS_X11)
# include <qtextstream.h>
# include <qt_x11_p.h>
#endif
#ifndef QT_NO_EGL
#if defined(QT_OPENGL_ES_2)
# include <GLES2/gl2.h>
#endif
#if defined(QT_GLES_EGL)
# include <GLES/egl.h>
#else
# include <EGL/egl.h>
#endif
#if !defined(EGL_VERSION_1_2)
typedef unsigned int EGLenum;
typedef void *EGLClientBuffer;
#endif
#else
//types from egltypes.h for compiling stub without EGL headers
typedef int EGLBoolean;
typedef int EGLint;
typedef int EGLenum;
typedef int NativeDisplayType;
typedef void* NativeWindowType;
typedef void* NativePixmapType;
typedef int EGLDisplay;
typedef int EGLConfig;
typedef int EGLSurface;
typedef int EGLContext;
typedef int EGLClientBuffer;
#define EGL_NONE 0x3038 /* Attrib list terminator */
#endif
// Internally we use the EGL-prefixed native types which are used in EGL >= 1.3.
// For older versions of EGL, we have to define these types ourselves here:
#if !defined(EGL_VERSION_1_3) && !defined(QEGL_NATIVE_TYPES_DEFINED)
#undef EGLNativeWindowType
#undef EGLNativePixmapType
#undef EGLNativeDisplayType
typedef NativeWindowType EGLNativeWindowType;
typedef NativePixmapType EGLNativePixmapType;
typedef NativeDisplayType EGLNativeDisplayType;
#define QEGL_NATIVE_TYPES_DEFINED 1
#endif
QT_END_INCLUDE_NAMESPACE
#include <QtGui/qpaintdevice.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
#define QEGL_NO_CONFIG ((EGLConfig)-1)
#ifndef EGLAPIENTRY
#define EGLAPIENTRY
#endif
// Declare/define the bits of EGL_KHR_image_base we need:
#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
typedef void *EGLImageKHR;
#if !defined(EGL_NO_IMAGE_KHR)
#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
#endif
#if !defined(EGL_IMAGE_PRESERVED_KHR)
#define EGL_IMAGE_PRESERVED_KHR 0x30D2
#endif
#if !defined(EGL_KHR_image_base)
#define EGL_KHR_image_base
#endif
#endif
#if !defined(EGL_KHR_image)
#define EGL_NATIVE_PIXMAP_KHR 0x30B0
#endif
#if !defined(EGL_KHR_image_pixmap)
#define EGL_KHR_image_pixmap
#endif
class QEglProperties;
namespace QEgl {
enum API
{
OpenGL,
};
enum PixelFormatMatch
{
ExactPixelFormat,
BestPixelFormat
};
enum ConfigOption
{
NoOptions = 0,
Translucent = 0x01,
Renderable = 0x02 // Config will be compatable with the paint engines (VG or GL)
};
Q_DECLARE_FLAGS(ConfigOptions, ConfigOption)
// Most of the time we use the same config for things like widgets & pixmaps, so rather than
// go through the eglChooseConfig loop every time, we use defaultConfig, which will return
// the config for a particular device/api/option combo. This function assumes that once a
// config is chosen for a particular combo, it's safe to always use that combo.
Q_GUI_EXPORT EGLConfig defaultConfig(int devType, API api, ConfigOptions options);
Q_GUI_EXPORT EGLConfig chooseConfig(const QEglProperties* configAttribs, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
Q_GUI_EXPORT EGLSurface createSurface(QPaintDevice *device, EGLConfig cfg, const QEglProperties *surfaceAttribs = 0);
Q_GUI_EXPORT void dumpAllConfigs();
#ifdef QT_NO_EGL
Q_GUI_EXPORT QString errorString(EGLint code = 0);
#else
Q_GUI_EXPORT QString errorString(EGLint code = eglGetError());
#endif
Q_GUI_EXPORT QString extensions();
Q_GUI_EXPORT bool hasExtension(const char* extensionName);
Q_GUI_EXPORT EGLDisplay display();
Q_GUI_EXPORT EGLNativeDisplayType nativeDisplay();
Q_GUI_EXPORT EGLNativeWindowType nativeWindow(QWidget*);
Q_GUI_EXPORT EGLNativePixmapType nativePixmap(QPixmap*);
// Extension functions
Q_GUI_EXPORT EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
Q_GUI_EXPORT EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img);
Q_GUI_EXPORT EGLBoolean eglSwapBuffersRegion2NOK(EGLDisplay dpy, EGLSurface surface, EGLint count, const EGLint *rects);
#ifdef Q_WS_X11
#include <X11/Xutil.h>
Q_GUI_EXPORT VisualID getCompatibleVisualId(EGLConfig config);
#endif
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QEgl::ConfigOptions)
QT_END_NAMESPACE
#endif //QEGL_P_H

View file

@ -1,473 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include <QtGui/qt_x11_p.h>
#include <QtGui/qx11info_x11.h>
#include <QtGui/qpixmapdata_p.h>
#include <QtGui/qpixmap_x11_p.h>
#include <QtGui/qimagepixmapcleanuphooks_p.h>
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
#include <QtGui/qcolormap.h>
#include "QtGui/qegl_p.h"
#include "QtGui/qeglcontext_p.h"
QT_BEGIN_NAMESPACE
EGLNativeDisplayType QEgl::nativeDisplay()
{
Display *xdpy = QX11Info::display();
if (!xdpy) {
qWarning("QEglContext::getDisplay(): X11 display is not open");
return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY);
}
return EGLNativeDisplayType(xdpy);
}
EGLNativeWindowType QEgl::nativeWindow(QWidget* widget)
{
return (EGLNativeWindowType)(widget->winId());
}
EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap)
{
return (EGLNativePixmapType)(pixmap->handle());
}
static int countBits(unsigned long mask)
{
int count = 0;
while (mask != 0) {
if (mask & 1)
++count;
mask >>= 1;
}
return count;
}
// Set the pixel format parameters from the visual in "xinfo".
void QEglProperties::setVisualFormat(const QX11Info *xinfo)
{
if (!xinfo)
return;
Visual *visual = (Visual*)xinfo->visual();
if (!visual)
return;
if (visual->c_class != TrueColor && visual->c_class != DirectColor)
return;
setValue(EGL_RED_SIZE, countBits(visual->red_mask));
setValue(EGL_GREEN_SIZE, countBits(visual->green_mask));
setValue(EGL_BLUE_SIZE, countBits(visual->blue_mask));
EGLint alphaBits = 0;
#if !defined(QT_NO_XRENDER)
XRenderPictFormat *format;
format = XRenderFindVisualFormat(xinfo->display(), visual);
if (format && (format->type == PictTypeDirect) && format->direct.alphaMask) {
alphaBits = countBits(format->direct.alphaMask);
qDebug("QEglProperties::setVisualFormat() - visual's alphaMask is %d", alphaBits);
}
#endif
setValue(EGL_ALPHA_SIZE, alphaBits);
}
extern const QX11Info *qt_x11Info(const QPaintDevice *pd);
// Set pixel format and other properties based on a paint device.
void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev)
{
if (!dev)
return;
if (dev->devType() == QInternal::Image)
setPixelFormat(static_cast<QImage *>(dev)->format());
else
setVisualFormat(qt_x11Info(dev));
}
//#define QT_DEBUG_X11_VISUAL_SELECTION 1
VisualID QEgl::getCompatibleVisualId(EGLConfig config)
{
VisualID visualId = 0;
EGLint eglValue = 0;
EGLint configRedSize = 0;
eglGetConfigAttrib(display(), config, EGL_RED_SIZE, &configRedSize);
EGLint configGreenSize = 0;
eglGetConfigAttrib(display(), config, EGL_GREEN_SIZE, &configGreenSize);
EGLint configBlueSize = 0;
eglGetConfigAttrib(display(), config, EGL_BLUE_SIZE, &configBlueSize);
EGLint configAlphaSize = 0;
eglGetConfigAttrib(display(), config, EGL_ALPHA_SIZE, &configAlphaSize);
eglGetConfigAttrib(display(), config, EGL_CONFIG_ID, &eglValue);
int configId = eglValue;
// See if EGL provided a valid VisualID:
eglGetConfigAttrib(display(), config, EGL_NATIVE_VISUAL_ID, &eglValue);
visualId = (VisualID)eglValue;
if (visualId) {
// EGL has suggested a visual id, so get the rest of the visual info for that id:
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
visualInfoTemplate.visualid = visualId;
XVisualInfo *chosenVisualInfo;
int matchingCount = 0;
chosenVisualInfo = XGetVisualInfo(X11->display, VisualIDMask, &visualInfoTemplate, &matchingCount);
if (chosenVisualInfo) {
// Skip size checks if implementation supports non-matching visual
// and config (http://bugreports.qt-project.org/browse/QTBUG-9444).
if (QEgl::hasExtension("EGL_NV_post_convert_rounding")) {
XFree(chosenVisualInfo);
return visualId;
}
int visualRedSize = countBits(chosenVisualInfo->red_mask);
int visualGreenSize = countBits(chosenVisualInfo->green_mask);
int visualBlueSize = countBits(chosenVisualInfo->blue_mask);
int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size
#if !defined(QT_NO_XRENDER)
if (X11->use_xrender) {
// If we have XRender, actually check the visual supplied by EGL is ARGB
XRenderPictFormat *format;
format = XRenderFindVisualFormat(X11->display, chosenVisualInfo->visual);
if (format && (format->type == PictTypeDirect))
visualAlphaSize = countBits(format->direct.alphaMask);
}
#endif
bool visualMatchesConfig = false;
if ( visualRedSize == configRedSize &&
visualGreenSize == configGreenSize &&
visualBlueSize == configBlueSize )
{
// We need XRender to check the alpha channel size of the visual. If we don't have
// the alpha size, we don't check it against the EGL config's alpha size.
if (visualAlphaSize >= 0)
visualMatchesConfig = visualAlphaSize == configAlphaSize;
else
visualMatchesConfig = true;
}
if (!visualMatchesConfig) {
if (visualAlphaSize >= 0) {
qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable",
(int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize,
configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize);
} else {
qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable",
(int)visualId, visualRedSize, visualGreenSize, visualBlueSize,
configId, configRedSize, configGreenSize, configBlueSize);
}
visualId = 0;
}
} else {
qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID",
(int)visualId, configId);
visualId = 0;
}
XFree(chosenVisualInfo);
}
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
else
qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId);
#endif
if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
if (configAlphaSize > 0)
qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId);
else
qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId);
#endif
return visualId;
}
// If EGL didn't give us a valid visual ID, try XRender
#if !defined(QT_NO_XRENDER)
if (!visualId && X11->use_xrender) {
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
visualInfoTemplate.c_class = TrueColor;
XVisualInfo *matchingVisuals;
int matchingCount = 0;
matchingVisuals = XGetVisualInfo(X11->display,
VisualClassMask,
&visualInfoTemplate,
&matchingCount);
for (int i = 0; i < matchingCount; ++i) {
XRenderPictFormat *format;
format = XRenderFindVisualFormat(X11->display, matchingVisuals[i].visual);
// Check the format for the visual matches the EGL config
if ( (countBits(format->direct.redMask) == configRedSize) &&
(countBits(format->direct.greenMask) == configGreenSize) &&
(countBits(format->direct.blueMask) == configBlueSize) &&
(countBits(format->direct.alphaMask) == configAlphaSize) )
{
visualId = matchingVisuals[i].visualid;
break;
}
}
if (matchingVisuals)
XFree(matchingVisuals);
}
if (visualId) {
# ifdef QT_DEBUG_X11_VISUAL_SELECTION
if (configAlphaSize > 0)
qDebug("Using ARGB Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
else
qDebug("Using Opaque Visual ID %d provided by XRender for EGL config %d", (int)visualId, configId);
# endif // QT_DEBUG_X11_VISUAL_SELECTION
return visualId;
}
# ifdef QT_DEBUG_X11_VISUAL_SELECTION
else
qDebug("Failed to find an XVisual which matches EGL config %d using XRender", configId);
# endif // QT_DEBUG_X11_VISUAL_SELECTION
#endif //!defined(QT_NO_XRENDER)
// Finally, if XRender also failed to find a visual (or isn't present), try to
// use XGetVisualInfo and only use the bit depths to match on:
if (!visualId) {
XVisualInfo visualInfoTemplate;
memset(&visualInfoTemplate, 0, sizeof(XVisualInfo));
XVisualInfo *matchingVisuals;
int matchingCount = 0;
visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize;
matchingVisuals = XGetVisualInfo(X11->display,
VisualDepthMask,
&visualInfoTemplate,
&matchingCount);
if (!matchingVisuals) {
// Try again without taking the alpha channel into account:
visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize;
matchingVisuals = XGetVisualInfo(X11->display,
VisualDepthMask,
&visualInfoTemplate,
&matchingCount);
}
if (matchingVisuals) {
visualId = matchingVisuals[0].visualid;
XFree(matchingVisuals);
}
}
if (visualId) {
#ifdef QT_DEBUG_X11_VISUAL_SELECTION
qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId);
#endif
return visualId;
}
qWarning("Unable to find an X11 visual which matches EGL config %d", configId);
return (VisualID)0;
}
void qt_set_winid_on_widget(QWidget* w, Qt::HANDLE id)
{
w->create(id);
}
// NOTE: The X11 version of createSurface will re-create the native drawable if it's visual doesn't
// match the one for the passed in EGLConfig
EGLSurface QEgl::createSurface(QPaintDevice *device, EGLConfig config, const QEglProperties *properties)
{
int devType = device->devType();
if (devType == QInternal::Pbuffer) {
// TODO
return EGL_NO_SURFACE;
}
QX11PixmapData *x11PixmapData = 0;
if (devType == QInternal::Pixmap) {
QPixmapData *pmd = static_cast<QPixmap*>(device)->data_ptr().data();
if (pmd->classId() == QPixmapData::X11Class)
x11PixmapData = static_cast<QX11PixmapData*>(pmd);
else {
// TODO: Replace the pixmap's data with a new QX11PixmapData
qWarning("WARNING: Creating an EGL surface on a QPixmap is only supported for QX11PixmapData");
return EGL_NO_SURFACE;
}
} else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
qWarning("WARNING: Creating an EGLSurface for device type %d isn't supported", devType);
return EGL_NO_SURFACE;
}
VisualID visualId = QEgl::getCompatibleVisualId(config);
EGLint alphaSize;
eglGetConfigAttrib(QEgl::display(), config, EGL_ALPHA_SIZE, &alphaSize);
if (devType == QInternal::Widget) {
QWidget *widget = static_cast<QWidget*>(device);
VisualID currentVisualId = 0;
if (widget->testAttribute(Qt::WA_WState_Created))
currentVisualId = XVisualIDFromVisual((Visual*)widget->x11Info().visual());
if (currentVisualId != visualId) {
// The window is either not created or has the wrong visual. Either way, we need
// to create a window with the correct visual and call create() on the widget:
bool visible = widget->isVisible();
if (visible)
widget->hide();
XVisualInfo visualInfo;
visualInfo.visualid = visualId;
{
XVisualInfo *visualInfoPtr;
int matchingCount = 0;
visualInfoPtr = XGetVisualInfo(widget->x11Info().display(), VisualIDMask,
&visualInfo, &matchingCount);
Q_ASSERT(visualInfoPtr); // visualId really should be valid!
visualInfo = *visualInfoPtr;
XFree(visualInfoPtr);
}
Window parentWindow = RootWindow(widget->x11Info().display(), widget->x11Info().screen());
if (widget->parentWidget())
parentWindow = widget->parentWidget()->winId();
XSetWindowAttributes windowAttribs;
QColormap colmap = QColormap::instance(widget->x11Info().screen());
windowAttribs.background_pixel = colmap.pixel(widget->palette().color(widget->backgroundRole()));
windowAttribs.border_pixel = colmap.pixel(Qt::black);
unsigned int valueMask = CWBackPixel|CWBorderPixel;
if (alphaSize > 0) {
windowAttribs.colormap = XCreateColormap(widget->x11Info().display(), parentWindow,
visualInfo.visual, AllocNone);
valueMask |= CWColormap;
}
Window window = XCreateWindow(widget->x11Info().display(), parentWindow,
widget->x(), widget->y(), widget->width(), widget->height(),
0, visualInfo.depth, InputOutput, visualInfo.visual,
valueMask, &windowAttribs);
// This is a nasty hack to get round the fact that we can't be a friend of QWidget:
qt_set_winid_on_widget(widget, window);
if (visible)
widget->show();
}
// At this point, the widget's window should be created and have the correct visual. Now we
// just need to create the EGL surface for it:
const int *props;
if (properties)
props = properties->properties();
else
props = 0;
EGLSurface surf = eglCreateWindowSurface(QEgl::display(), config, (EGLNativeWindowType)widget->winId(), props);
if (surf == EGL_NO_SURFACE)
qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
return surf;
}
if (x11PixmapData) {
// X11 Pixmaps are only created with a depth, so that's all we need to check
EGLint configDepth;
eglGetConfigAttrib(QEgl::display(), config, EGL_BUFFER_SIZE , &configDepth);
if (x11PixmapData->depth() != configDepth) {
// The bit depths are wrong which means the EGLConfig isn't compatable with
// this pixmap. So we need to replace the pixmap's existing data with a new
// one which is created with the correct depth:
#ifndef QT_NO_XRENDER
if (configDepth == 32) {
qWarning("Warning: EGLConfig's depth (32) != pixmap's depth (%d), converting to ARGB32",
x11PixmapData->depth());
x11PixmapData->convertToARGB32(true);
} else
#endif
{
qWarning("Warning: EGLConfig's depth (%d) != pixmap's depth (%d)",
configDepth, x11PixmapData->depth());
}
}
QEglProperties surfaceAttribs;
// If the pixmap can't be bound to a texture, it's pretty useless
surfaceAttribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
if (alphaSize > 0)
surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA);
else
surfaceAttribs.setValue(EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB);
EGLSurface surf = eglCreatePixmapSurface(QEgl::display(), config,
(EGLNativePixmapType) x11PixmapData->handle(),
surfaceAttribs.properties());
x11PixmapData->gl_surface = (void*)surf;
QImagePixmapCleanupHooks::enableCleanupHooks(x11PixmapData);
return surf;
}
return EGL_NO_SURFACE;
}
QT_END_NAMESPACE

View file

@ -1,118 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QEGLCONTEXT_P_H
#define QEGLCONTEXT_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 QtOpenGL and QtOpenVG modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qsize.h>
#include <QtGui/qimage.h>
#include <qegl_p.h>
#include <qeglproperties_p.h>
QT_BEGIN_NAMESPACE
class Q_GUI_EXPORT QEglContext
{
public:
QEglContext();
~QEglContext();
bool isValid() const;
bool isCurrent() const;
bool isSharing() const { return sharing; }
QEgl::API api() const { return apiType; }
void setApi(QEgl::API api) { apiType = api; }
bool chooseConfig(const QEglProperties& properties, QEgl::PixelFormatMatch match = QEgl::ExactPixelFormat);
bool createContext(QEglContext *shareContext = 0, const QEglProperties *properties = 0);
void destroyContext();
EGLSurface createSurface(QPaintDevice *device, const QEglProperties *properties = 0);
void destroySurface(EGLSurface surface);
bool makeCurrent(EGLSurface surface);
bool doneCurrent();
bool lazyDoneCurrent();
bool swapBuffers(EGLSurface surface);
bool swapBuffersRegion2NOK(EGLSurface surface, const QRegion *region);
int configAttrib(int name) const;
EGLContext context() const { return ctx; }
void setContext(EGLContext context) { ctx = context; ownsContext = false;}
EGLDisplay display() {return QEgl::display();}
EGLConfig config() const { return cfg; }
void setConfig(EGLConfig config) { cfg = config; }
private:
QEgl::API apiType;
EGLContext ctx;
EGLConfig cfg;
EGLSurface currentSurface;
bool current;
bool ownsContext;
bool sharing;
bool apiChanged;
static QEglContext *currentContext(QEgl::API api);
static void setCurrentContext(QEgl::API api, QEglContext *context);
friend class QMeeGoGraphicsSystem;
friend class QMeeGoPixmapData;
};
QT_END_NAMESPACE
#endif // QEGLCONTEXT_P_H

View file

@ -1,536 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
#include "qeglproperties_p.h"
#include "qeglcontext_p.h"
QT_BEGIN_NAMESPACE
// Initialize a property block.
QEglProperties::QEglProperties()
{
props.append(EGL_NONE);
}
QEglProperties::QEglProperties(EGLConfig cfg)
{
props.append(EGL_NONE);
for (int name = 0x3020; name <= 0x304F; ++name) {
EGLint value;
if (name != EGL_NONE && eglGetConfigAttrib(QEgl::display(), cfg, name, &value))
setValue(name, value);
}
eglGetError(); // Clear the error state.
}
// Fetch the current value associated with a property.
int QEglProperties::value(int name) const
{
for (int index = 0; index < (props.size() - 1); index += 2) {
if (props[index] == name)
return props[index + 1];
}
// If the attribute has not been explicitly set, return the EGL default
// The following defaults were taken from the EGL 1.4 spec:
switch(name) {
case EGL_BUFFER_SIZE: return 0;
case EGL_RED_SIZE: return 0;
case EGL_GREEN_SIZE: return 0;
case EGL_BLUE_SIZE: return 0;
case EGL_ALPHA_SIZE: return 0;
#ifdef EGL_LUMINANCE_SIZE
case EGL_LUMINANCE_SIZE: return 0;
#endif
#ifdef EGL_ALPHA_MASK_SIZE
case EGL_ALPHA_MASK_SIZE: return 0;
#endif
#ifdef EGL_BIND_TO_TEXTURE_RGB
case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE;
#endif
#ifdef EGL_BIND_TO_TEXTURE_RGBA
case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE;
#endif
#ifdef EGL_COLOR_BUFFER_TYPE
case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER;
#endif
case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE;
case EGL_CONFIG_ID: return EGL_DONT_CARE;
case EGL_DEPTH_SIZE: return 0;
case EGL_LEVEL: return 0;
case EGL_NATIVE_RENDERABLE: return EGL_DONT_CARE;
case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE;
case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE;
case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE;
#ifdef EGL_RENDERABLE_TYPE
case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT;
#endif
case EGL_SAMPLE_BUFFERS: return 0;
case EGL_SAMPLES: return 0;
case EGL_STENCIL_SIZE: return 0;
case EGL_SURFACE_TYPE: return EGL_WINDOW_BIT;
case EGL_TRANSPARENT_TYPE: return EGL_NONE;
case EGL_TRANSPARENT_RED_VALUE: return EGL_DONT_CARE;
case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE;
case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE;
#ifdef EGL_VERSION_1_3
case EGL_CONFORMANT: return 0;
case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE;
#endif
case EGL_MAX_PBUFFER_HEIGHT:
case EGL_MAX_PBUFFER_WIDTH:
case EGL_MAX_PBUFFER_PIXELS:
case EGL_NATIVE_VISUAL_ID:
case EGL_NONE:
// Attribute does not affect config selection.
return EGL_DONT_CARE;
default:
// Attribute is unknown in EGL <= 1.4.
return EGL_DONT_CARE;
}
}
// Set the value associated with a property, replacing an existing
// value if there is one.
void QEglProperties::setValue(int name, int value)
{
for (int index = 0; index < (props.size() - 1); index += 2) {
if (props[index] == name) {
props[index + 1] = value;
return;
}
}
props[props.size() - 1] = name;
props.append(value);
props.append(EGL_NONE);
}
// Remove a property value. Returns false if the property is not present.
bool QEglProperties::removeValue(int name)
{
for (int index = 0; index < (props.size() - 1); index += 2) {
if (props[index] == name) {
while ((index + 2) < props.size()) {
props[index] = props[index + 2];
++index;
}
props.resize(props.size() - 2);
return true;
}
}
return false;
}
void QEglProperties::setDeviceType(int devType)
{
if (devType == QInternal::Pixmap || devType == QInternal::Image)
setValue(EGL_SURFACE_TYPE, EGL_PIXMAP_BIT);
else if (devType == QInternal::Pbuffer)
setValue(EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
else
setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
}
// Sets the red, green, blue, and alpha sizes based on a pixel format.
// Normally used to match a configuration request to the screen format.
void QEglProperties::setPixelFormat(QImage::Format pixelFormat)
{
int red, green, blue, alpha;
switch (pixelFormat) {
case QImage::Format_RGB32:
case QImage::Format_RGB888:
red = green = blue = 8; alpha = 0; break;
case QImage::Format_ARGB32:
case QImage::Format_ARGB32_Premultiplied:
red = green = blue = alpha = 8; break;
case QImage::Format_RGB16:
red = 5; green = 6; blue = 5; alpha = 0; break;
case QImage::Format_ARGB8565_Premultiplied:
red = 5; green = 6; blue = 5; alpha = 8; break;
case QImage::Format_RGB666:
red = green = blue = 6; alpha = 0; break;
case QImage::Format_ARGB6666_Premultiplied:
red = green = blue = alpha = 6; break;
case QImage::Format_RGB555:
red = green = blue = 5; alpha = 0; break;
case QImage::Format_ARGB8555_Premultiplied:
red = green = blue = 5; alpha = 8; break;
case QImage::Format_RGB444:
red = green = blue = 4; alpha = 0; break;
case QImage::Format_ARGB4444_Premultiplied:
red = green = blue = alpha = 4; break;
default:
qWarning() << "QEglProperties::setPixelFormat(): Unsupported pixel format";
red = green = blue = alpha = 1; break;
}
setValue(EGL_RED_SIZE, red);
setValue(EGL_GREEN_SIZE, green);
setValue(EGL_BLUE_SIZE, blue);
setValue(EGL_ALPHA_SIZE, alpha);
}
void QEglProperties::setRenderableType(QEgl::API api)
{
#ifdef EGL_RENDERABLE_TYPE
#if defined(QT_OPENGL_ES_2)
if (api == QEgl::OpenGL)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT);
#elif defined(QT_OPENGL_ES)
if (api == QEgl::OpenGL)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
#elif defined(EGL_OPENGL_BIT)
if (api == QEgl::OpenGL)
setValue(EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT);
#endif
#else
Q_UNUSED(api);
#endif
}
// Reduce the complexity of a configuration request to ask for less
// because the previous request did not result in success. Returns
// true if the complexity was reduced, or false if no further
// reductions in complexity are possible.
bool QEglProperties::reduceConfiguration()
{
#ifdef EGL_SWAP_BEHAVIOR
if (value(EGL_SWAP_BEHAVIOR) != EGL_DONT_CARE)
removeValue(EGL_SWAP_BEHAVIOR);
#endif
// EGL chooses configs with the highest color depth over
// those with smaller (but faster) lower color depths. One
// way around this is to set EGL_BUFFER_SIZE to 16, which
// trumps the others. Of course, there may not be a 16-bit
// config available, so it's the first restraint we remove.
if (value(EGL_BUFFER_SIZE) == 16) {
removeValue(EGL_BUFFER_SIZE);
return true;
}
if (removeValue(EGL_SAMPLE_BUFFERS)) {
removeValue(EGL_SAMPLES);
return true;
}
if (removeValue(EGL_ALPHA_SIZE)) {
#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB)
if (removeValue(EGL_BIND_TO_TEXTURE_RGBA))
setValue(EGL_BIND_TO_TEXTURE_RGB, TRUE);
#endif
return true;
}
if (removeValue(EGL_STENCIL_SIZE))
return true;
if (removeValue(EGL_DEPTH_SIZE))
return true;
#ifdef EGL_BIND_TO_TEXTURE_RGB
if (removeValue(EGL_BIND_TO_TEXTURE_RGB))
return true;
#endif
return false;
}
static void addTag(QString& str, const QString& tag)
{
int lastnl = str.lastIndexOf(QLatin1String("\n"));
if (lastnl == -1)
lastnl = 0;
if ((str.length() - lastnl) >= 50)
str += QLatin1String("\n ");
str += tag;
}
// Convert a property list to a string suitable for debug output.
QString QEglProperties::toString() const
{
QString str;
int val;
val = value(EGL_CONFIG_ID);
if (val != EGL_DONT_CARE) {
str += QLatin1String("id=");
str += QString::number(val);
str += QLatin1Char(' ');
}
#ifdef EGL_RENDERABLE_TYPE
val = value(EGL_RENDERABLE_TYPE);
if (val != EGL_DONT_CARE) {
str += QLatin1String("type=");
QStringList types;
if ((val & EGL_OPENGL_ES_BIT) != 0)
types += QLatin1String("es1");
#ifdef EGL_OPENGL_ES2_BIT
if ((val & EGL_OPENGL_ES2_BIT) != 0)
types += QLatin1String("es2");
#endif
#ifdef EGL_OPENGL_BIT
if ((val & EGL_OPENGL_BIT) != 0)
types += QLatin1String("gl");
#endif
if ((val & ~7) != 0)
types += QString::number(val);
str += types.join(QLatin1String(","));
} else {
str += QLatin1String("type=any");
}
#else
str += QLatin1String("type=es1");
#endif
int red = value(EGL_RED_SIZE);
int green = value(EGL_GREEN_SIZE);
int blue = value(EGL_BLUE_SIZE);
int alpha = value(EGL_ALPHA_SIZE);
int bufferSize = value(EGL_BUFFER_SIZE);
if (bufferSize == (red + green + blue + alpha))
bufferSize = 0;
str += QLatin1String(" rgba=");
str += QString::number(red);
str += QLatin1Char(',');
str += QString::number(green);
str += QLatin1Char(',');
str += QString::number(blue);
str += QLatin1Char(',');
str += QString::number(alpha);
if (bufferSize != 0) {
// Only report buffer size if different than r+g+b+a.
str += QLatin1String(" buffer-size=");
str += QString::number(bufferSize);
}
#ifdef EGL_COLOR_BUFFER_TYPE
val = value(EGL_COLOR_BUFFER_TYPE);
if (val == EGL_LUMINANCE_BUFFER) {
addTag(str, QLatin1String(" color-buffer-type=luminance"));
} else if (val != EGL_DONT_CARE && val != EGL_RGB_BUFFER) {
addTag(str, QLatin1String(" color-buffer-type="));
str += QString::number(val, 16);
}
#endif
val = value(EGL_DEPTH_SIZE);
if (val != 0) {
addTag(str, QLatin1String(" depth="));
str += QString::number(val);
}
val = value(EGL_STENCIL_SIZE);
if (val != 0) {
addTag(str, QLatin1String(" stencil="));
str += QString::number(val);
}
val = value(EGL_SURFACE_TYPE);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" surface-type="));
QStringList types;
if ((val & EGL_WINDOW_BIT) != 0)
types += QLatin1String("window");
if ((val & EGL_PIXMAP_BIT) != 0)
types += QLatin1String("pixmap");
if ((val & EGL_PBUFFER_BIT) != 0)
types += QLatin1String("pbuffer");
if ((val & ~(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) != 0) {
types += QString::number(val);
}
str += types.join(QLatin1String(","));
}
val = value(EGL_CONFIG_CAVEAT);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" caveat="));
if (val == EGL_NONE)
str += QLatin1String("none");
else if (val == EGL_SLOW_CONFIG)
str += QLatin1String("slow");
else if (val == EGL_NON_CONFORMANT_CONFIG)
str += QLatin1String("non-conformant");
else
str += QString::number(val, 16);
}
val = value(EGL_LEVEL);
if (val != 0) {
addTag(str, QLatin1String(" level="));
str += QString::number(val);
}
int width, height, pixels;
width = value(EGL_MAX_PBUFFER_WIDTH);
height = value(EGL_MAX_PBUFFER_HEIGHT);
pixels = value(EGL_MAX_PBUFFER_PIXELS);
if (height != EGL_DONT_CARE || width != EGL_DONT_CARE) {
addTag(str, QLatin1String(" max-pbuffer-size="));
str += QString::number(width);
str += QLatin1Char('x');
str += QString::number(height);
if (pixels != (width * height)) {
addTag(str, QLatin1String(" max-pbuffer-pixels="));
str += QString::number(pixels);
}
}
val = value(EGL_NATIVE_RENDERABLE);
if (val != EGL_DONT_CARE) {
if (val)
addTag(str, QLatin1String(" native-renderable=true"));
else
addTag(str, QLatin1String(" native-renderable=false"));
}
val = value(EGL_NATIVE_VISUAL_ID);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" visual-id="));
str += QString::number(val);
}
val = value(EGL_NATIVE_VISUAL_TYPE);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" visual-type="));
str += QString::number(val);
}
#ifdef EGL_PRESERVED_RESOURCES
val = value(EGL_PRESERVED_RESOURCES);
if (val != EGL_DONT_CARE) {
if (val)
addTag(str, QLatin1String(" preserved-resources=true"));
else
addTag(str, QLatin1String(" preserved-resources=false"));
}
#endif
val = value(EGL_SAMPLES);
if (val != 0) {
addTag(str, QLatin1String(" samples="));
str += QString::number(val);
}
val = value(EGL_SAMPLE_BUFFERS);
if (val != 0) {
addTag(str, QLatin1String(" sample-buffers="));
str += QString::number(val);
}
val = value(EGL_TRANSPARENT_TYPE);
if (val == EGL_TRANSPARENT_RGB) {
addTag(str, QLatin1String(" transparent-rgb="));
str += QString::number(value(EGL_TRANSPARENT_RED_VALUE));
str += QLatin1Char(',');
str += QString::number(value(EGL_TRANSPARENT_GREEN_VALUE));
str += QLatin1Char(',');
str += QString::number(value(EGL_TRANSPARENT_BLUE_VALUE));
}
#if defined(EGL_BIND_TO_TEXTURE_RGB) && defined(EGL_BIND_TO_TEXTURE_RGBA)
val = value(EGL_BIND_TO_TEXTURE_RGB);
int val2 = value(EGL_BIND_TO_TEXTURE_RGBA);
if (val != EGL_DONT_CARE || val2 != EGL_DONT_CARE) {
addTag(str, QLatin1String(" bind-texture="));
if (val == EGL_TRUE)
str += QLatin1String("rgb");
else
str += QLatin1String("no-rgb");
if (val2 == EGL_TRUE)
str += QLatin1String(",rgba");
else
str += QLatin1String(",no-rgba");
}
#endif
#ifdef EGL_MIN_SWAP_INTERVAL
val = value(EGL_MIN_SWAP_INTERVAL);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" min-swap-interval="));
str += QString::number(val);
}
#endif
#ifdef EGL_MIN_SWAP_INTERVAL
val = value(EGL_MAX_SWAP_INTERVAL);
if (val != EGL_DONT_CARE) {
addTag(str, QLatin1String(" max-swap-interval="));
str += QString::number(val);
}
#endif
#ifdef EGL_LUMINANCE_SIZE
val = value(EGL_LUMINANCE_SIZE);
if (val != 0) {
addTag(str, QLatin1String(" luminance="));
str += QString::number(val);
}
#endif
#ifdef EGL_ALPHA_MASK_SIZE
val = value(EGL_ALPHA_MASK_SIZE);
if (val != 0) {
addTag(str, QLatin1String(" alpha-mask="));
str += QString::number(val);
}
#endif
#ifdef EGL_CONFORMANT
val = value(EGL_CONFORMANT);
if (val != 0) {
if (val)
addTag(str, QLatin1String(" conformant=true"));
else
addTag(str, QLatin1String(" conformant=false"));
}
#endif
return str;
}
QT_END_NAMESPACE

View file

@ -1,99 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QEGLPROPERTIES_P_H
#define QEGLPROPERTIES_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 QtOpenGL and QtOpenVG modules. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qvarlengtharray.h>
#include <QtGui/qimage.h>
#include <qegl_p.h>
QT_BEGIN_NAMESPACE
class QX11Info;
class QPaintDevice;
class Q_GUI_EXPORT QEglProperties
{
public:
QEglProperties();
QEglProperties(EGLConfig);
QEglProperties(const QEglProperties& other) : props(other.props) {}
~QEglProperties() {}
int value(int name) const;
void setValue(int name, int value);
bool removeValue(int name);
bool isEmpty() const { return props[0] == EGL_NONE; }
const EGLint *properties() const { return props.constData(); }
void setPixelFormat(QImage::Format pixelFormat);
#ifdef Q_WS_X11
void setVisualFormat(const QX11Info *xinfo);
#endif
void setDeviceType(int devType);
void setPaintDeviceFormat(QPaintDevice *dev);
void setRenderableType(QEgl::API api);
bool reduceConfiguration();
QString toString() const;
private:
QVarLengthArray<EGLint> props;
};
QT_END_NAMESPACE
#endif // QEGLPROPERTIES_P_H

View file

@ -1921,8 +1921,7 @@ QGraphicsItem::CacheMode QGraphicsItem::cacheMode() const
spends redrawing from the cache. When enabled, the item's paint() function
will be called only once for each call to update(); for any subsequent
repaint requests, the Graphics View framework will redraw from the
cache. This approach works particularly well with QGLWidget, which stores
all the cache as OpenGL textures.
cache.
Be aware that QPixmapCache's cache limit may need to be changed to obtain
optimal performance.
@ -5644,10 +5643,9 @@ void QGraphicsItem::update(const QRectF &rect)
simply moving pixels from one location to another using memmove(). In most
cases this is faster than rerendering the entire area.
After scrolling, the item will issue an update for the newly exposed
areas. If scrolling is not supported (e.g., you are rendering to an OpenGL
viewport, which does not benefit from scroll optimizations), this function
is equivalent to calling update(\a rect).
After scrolling, the item will issue an update for the newly exposed areas.
If scrolling is not supported, this function is equivalent to calling
update(\a rect).
\bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache
is enabled; in all other cases calling this function is equivalent to calling

View file

@ -90,9 +90,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
By default, QGraphicsView provides a regular QWidget for the viewport
widget. You can access this widget by calling viewport(), or you can
replace it by calling setViewport(). To render using OpenGL, simply call
setViewport(new QGLWidget). QGraphicsView takes ownership of the viewport
widget.
replace it by calling setViewport(). QGraphicsView takes ownership of
the viewport widget.
QGraphicsView supports affine transformations, using QTransform. You can
either pass a matrix to setTransform(), or you can call one of the

View file

@ -18,7 +18,6 @@ set(GUI_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/image/qpixmapcache_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qpixmapdata_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qpixmapfilter_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qimagepixmapcleanuphooks_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qbmphandler_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qppmhandler_p.h
${CMAKE_CURRENT_SOURCE_DIR}/image/qxbmhandler_p.h
@ -43,7 +42,6 @@ set(GUI_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/image/qiconengineplugin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/image/qmovie.cpp
${CMAKE_CURRENT_SOURCE_DIR}/image/qpixmap_raster.cpp
${CMAKE_CURRENT_SOURCE_DIR}/image/qimagepixmapcleanuphooks.cpp
# Built-in image format support
${CMAKE_CURRENT_SOURCE_DIR}/image/qbmphandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/image/qppmhandler.cpp

View file

@ -50,7 +50,6 @@
#include "qstringlist.h"
#include "qvariant.h"
#include "qcolormap.h"
#include "qimagepixmapcleanuphooks_p.h"
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
@ -118,7 +117,7 @@ QImageData::QImageData()
dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
is_cached(false), paintEngine(0)
paintEngine(0)
{
}
@ -182,7 +181,6 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
d->depth = depth;
d->format = format;
d->has_alpha_clut = false;
d->is_cached = false;
d->bytes_per_line = bytes_per_line;
@ -200,8 +198,6 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format, int nu
QImageData::~QImageData()
{
if (is_cached)
QImagePixmapCleanupHooks::executeImageHooks((((qint64) ser_no) << 32) | ((qint64) detach_no));
delete paintEngine;
if (data && own_data)
free(data);
@ -1123,9 +1119,6 @@ QImage::operator QVariant() const
void QImage::detach()
{
if (d) {
if (d->is_cached && d->ref == 1)
QImagePixmapCleanupHooks::executeImageHooks(cacheKey());
if (d->ref != 1 || d->ro_data)
*this = copy();

View file

@ -91,7 +91,6 @@ struct Q_GUI_EXPORT QImageData { // internal image data
uint own_data : 1;
uint ro_data : 1;
uint has_alpha_clut : 1;
uint is_cached : 1;
bool checkForAlphaPixels() const;

View file

@ -1,149 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qimagepixmapcleanuphooks_p.h"
#include "qpixmapdata_p.h"
#include "qimage_p.h"
QT_BEGIN_NAMESPACE
Q_GLOBAL_STATIC(QImagePixmapCleanupHooks, qt_image_and_pixmap_cleanup_hooks)
QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
{
return qt_image_and_pixmap_cleanup_hooks();
}
void QImagePixmapCleanupHooks::addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.append(hook);
}
void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.append(hook);
}
void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
{
imageHooks.append(hook);
}
void QImagePixmapCleanupHooks::removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.removeAll(hook);
}
void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.removeAll(hook);
}
void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
{
imageHooks.removeAll(hook);
}
void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
// the global destructor for the pixmap and image hooks might have
// been called already if the app is "leaking" global
// pixmaps/images
if (!h)
return;
for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
h->pixmapModificationHooks[i](pmd);
}
void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
// the global destructor for the pixmap and image hooks might have
// been called already if the app is "leaking" global
// pixmaps/images
if (!h)
return;
for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
h->pixmapDestructionHooks[i](pmd);
}
void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
{
for (int i = 0; i < qt_image_and_pixmap_cleanup_hooks()->imageHooks.count(); ++i)
qt_image_and_pixmap_cleanup_hooks()->imageHooks[i](key);
}
void QImagePixmapCleanupHooks::enableCleanupHooks(QPixmapData *pixmapData)
{
pixmapData->is_cached = true;
}
void QImagePixmapCleanupHooks::enableCleanupHooks(const QPixmap &pixmap)
{
const_cast<QPixmap &>(pixmap).data_ptr().data()->is_cached = true;
}
void QImagePixmapCleanupHooks::enableCleanupHooks(const QImage &image)
{
const_cast<QImage &>(image).data_ptr()->is_cached = true;
}
bool QImagePixmapCleanupHooks::isImageCached(const QImage &image)
{
return const_cast<QImage &>(image).data_ptr()->is_cached;
}
bool QImagePixmapCleanupHooks::isPixmapCached(const QPixmap &pixmap)
{
return const_cast<QPixmap&>(pixmap).data_ptr().data()->is_cached;
}
QT_END_NAMESPACE

View file

@ -1,103 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QIMAGEPIXMAP_CLEANUPHOOKS_P_H
#define QIMAGEPIXMAP_CLEANUPHOOKS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtGui/qpixmap.h>
QT_BEGIN_NAMESPACE
typedef void (*_qt_image_cleanup_hook_64)(qint64);
typedef void (*_qt_pixmap_cleanup_hook_pmd)(QPixmapData*);
class QImagePixmapCleanupHooks;
class Q_GUI_EXPORT QImagePixmapCleanupHooks
{
public:
static QImagePixmapCleanupHooks *instance();
static void enableCleanupHooks(const QImage &image);
static void enableCleanupHooks(const QPixmap &pixmap);
static void enableCleanupHooks(QPixmapData *pixmapData);
static bool isImageCached(const QImage &image);
static bool isPixmapCached(const QPixmap &pixmap);
// Gets called when a pixmap data is about to be modified:
void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
// Gets called when a pixmap data is about to be destroyed:
void addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
// Gets called when an image is about to be modified or destroyed:
void addImageHook(_qt_image_cleanup_hook_64);
void removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
void removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
void removeImageHook(_qt_image_cleanup_hook_64);
static void executePixmapDataModificationHooks(QPixmapData*);
static void executePixmapDataDestructionHooks(QPixmapData*);
static void executeImageHooks(qint64 key);
private:
QList<_qt_image_cleanup_hook_64> imageHooks;
QList<_qt_pixmap_cleanup_hook_pmd> pixmapModificationHooks;
QList<_qt_pixmap_cleanup_hook_pmd> pixmapDestructionHooks;
};
QT_END_NAMESPACE
#endif // QIMAGEPIXMAP_CLEANUPHOOKS_P_H

View file

@ -41,7 +41,6 @@
#include "qpixmap.h"
#include "qpixmapdata_p.h"
#include "qimagepixmapcleanuphooks_p.h"
#include "qbitmap.h"
#include "qcolormap.h"
#include "qimage.h"
@ -1226,8 +1225,7 @@ bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags fla
In some cases it can be more beneficial to draw the pixmap to a
painter with a scale set rather than scaling the pixmap. This is
the case when the painter is for instance based on OpenGL or when
the scale factor changes rapidly.
the case when the scale factor changes rapidly.
\sa isNull(), {QPixmap#Pixmap Transformations}{Pixmap
Transformations}
@ -1740,9 +1738,6 @@ void QPixmap::detach()
rasterData->image.detach();
}
if (data->is_cached && data->ref == 1)
QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
if (data->ref != 1) {
*this = copy();
}

View file

@ -63,7 +63,6 @@
#include "qx11info_x11.h"
#include <qdrawhelper_p.h>
#include <qimage_p.h>
#include <qimagepixmapcleanuphooks_p.h>
#include <stdlib.h>
@ -1236,12 +1235,6 @@ void QX11PixmapData::fill(const QColor &fillColor)
QX11PixmapData::~QX11PixmapData()
{
// Cleanup hooks have to be called before the handles are freed
if (is_cached) {
QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
is_cached = false;
}
release();
}

View file

@ -45,7 +45,6 @@
#include <QtGui/qimagereader.h>
#include <qgraphicssystem_p.h>
#include <qapplication_p.h>
#include <qimagepixmapcleanuphooks_p.h>
QT_BEGIN_NAMESPACE
@ -74,23 +73,12 @@ QPixmapData::QPixmapData(PixelType pixelType, int objectId)
detach_no(0),
type(pixelType),
id(objectId),
ser_no(0),
is_cached(false)
ser_no(0)
{
}
QPixmapData::~QPixmapData()
{
// 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
// 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, QX11PixmapData will
// call the cleanup hooks itself before deleting the native pixmap and set is_cached to
// false.
if (is_cached) {
QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
is_cached = false;
}
}
QPixmapData *QPixmapData::createCompatiblePixmapData() const

View file

@ -69,7 +69,7 @@ public:
// Must match QPixmap::Type
PixmapType, BitmapType
};
enum ClassId { RasterClass, X11Class, OpenGLClass };
enum ClassId { RasterClass, X11Class };
QPixmapData(PixelType pixelType, int classId);
virtual ~QPixmapData();
@ -138,8 +138,6 @@ protected:
private:
friend class QPixmap;
friend class QX11PixmapData;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
friend class QGLTextureCache; //Needs to check the reference count
friend class QExplicitlySharedDataPointer<QPixmapData>;
QAtomicInt ref;
@ -148,7 +146,6 @@ private:
PixelType type;
int id;
int ser_no;
uint is_cached;
};
# define QT_XFORM_TYPE_MSBFIRST 0

View file

@ -69,41 +69,29 @@
#include "qstylesheetstyle_p.h"
#include "qstyle_p.h"
#include "qmessagebox.h"
#include <QtGui/qgraphicsproxywidget.h>
#include "qgraphicsproxywidget.h"
#include "qkeymapper_p.h"
#ifdef Q_WS_X11
#include <qt_x11_p.h>
#endif
#include "qguiplatformplugin_p.h"
#include <qthread.h>
#include <qthread_p.h>
#include <qfont_p.h>
#include <stdlib.h>
#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
#include <link.h>
#endif
#include "qthread.h"
#include "qthread_p.h"
#include "qfont_p.h"
#include "qapplication_p.h"
#include "qevent_p.h"
#include "qwidget_p.h"
#include "qapplication.h"
#include "qgesture.h"
#include "qgesturemanager_p.h"
#include "qdatetime.h"
#ifndef QT_NO_LIBRARY
#include "qlibrary.h"
#endif
#include "qdatetime.h"
#ifdef Q_WS_X11
#include <qt_x11_p.h>
#endif
#include <stdlib.h>
//#define ALIEN_DEBUG
@ -570,7 +558,7 @@ void QApplicationPrivate::process_cmdline()
\o -reverse, sets the application's layout direction to
Qt::RightToLeft
\o -graphicssystem, sets the backend to be used for on-screen widgets
and QPixmaps. Available options are \c{raster} and \c{opengl}.
and QPixmaps. Available options are \c{raster}.
\endlist
The X11 version of Qt supports some traditional X11 command line options:
@ -1352,8 +1340,7 @@ QStyle* QApplication::setStyle(const QString& style)
\since 4.5
Sets the default graphics backend to \a system, which will be used for
on-screen widgets and QPixmaps. The available systems are \c{"raster"}
and \c{"opengl"}.
on-screen widgets and QPixmaps. The available systems is \c{"raster"}.
There are several ways to set the graphics backend, in order of decreasing
precedence:
@ -1368,8 +1355,6 @@ QStyle* QApplication::setStyle(const QString& style)
\warning This function is only effective before the QApplication constructor
is called.
\note The \c{"opengl"} option is currently experimental.
*/
QString QApplication::graphicsSystem()

View file

@ -4657,41 +4657,6 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
if (isVisible())
QApplication::syncX();
if (d->extra->compress_events) {
// ConfigureNotify compression for faster opaque resizing
XEvent otherEvent;
while (XCheckTypedWindowEvent(X11->display, internalWinId(), ConfigureNotify,
&otherEvent)) {
if (qt_x11EventFilter(&otherEvent))
continue;
if (x11Event(&otherEvent))
continue;
if (otherEvent.xconfigure.event != otherEvent.xconfigure.window)
continue;
newSize.setWidth(otherEvent.xconfigure.width);
newSize.setHeight(otherEvent.xconfigure.height);
if (otherEvent.xconfigure.send_event || trust) {
newCPos.rx() = otherEvent.xconfigure.x +
otherEvent.xconfigure.border_width;
newCPos.ry() = otherEvent.xconfigure.y +
otherEvent.xconfigure.border_width;
isCPos = true;
}
}
#ifndef QT_NO_XSYNC
qt_sync_request_event_data sync_event;
sync_event.window = internalWinId();
for (XEvent ev;;) {
if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
break;
}
#endif // QT_NO_XSYNC
}
if (!isCPos) {
// we didn't get an updated position of the toplevel.
// either we haven't moved or there is a bug in the window manager.

View file

@ -227,8 +227,6 @@ QWidgetPrivate::QWidgetPrivate(int version)
, inDirtyList(0)
, isScrolled(0)
, isMoved(0)
, isGLWidget(0)
, usesDoubleBufferedGLContext(0)
, inSetParent(0)
#if defined(Q_WS_X11)
, picture(0)
@ -1915,12 +1913,6 @@ void QWidgetPrivate::updateIsOpaque()
#endif //QT_NO_GRAPHICSEFFECT
Q_Q(QWidget);
#ifdef Q_WS_X11
if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) {
setOpaque(false);
return;
}
#endif
if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) {
@ -4513,9 +4505,6 @@ void QWidget::unsetCursor()
active painter (if any) before rendering. For example:
\snippet doc/src/snippets/code/src_gui_kernel_qwidget.cpp 8
\note To obtain the contents of an OpenGL widget, use QGLWidget::grabFrameBuffer()
or QGLWidget::renderPixmap() instead.
*/
void QWidget::render(QPaintDevice *target, const QPoint &targetOffset,
const QRegion &sourceRegion, RenderFlags renderFlags)
@ -9574,14 +9563,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
d->resolveLocale();
break;
#ifdef Q_WS_X11
case Qt::WA_NoX11EventCompression:
if (!d->extra)
d->createExtra();
d->extra->compress_events = on;
break;
case Qt::WA_X11OpenGLOverlay:
d->updateIsOpaque();
break;
case Qt::WA_X11DoNotAcceptFocus:
if (testAttribute(Qt::WA_WState_Created))
d->updateX11AcceptFocus();

View file

@ -217,7 +217,6 @@ struct QWExtra {
// *************************** Platform specific values (bit fields first) **********
#if defined(Q_WS_X11) // <--------------------------------------------------------- X11
uint compress_events : 1;
WId xDndProxy; // XDND forwarding to embedded windows
#endif
};
@ -634,8 +633,6 @@ public:
uint inDirtyList : 1;
uint isScrolled : 1;
uint isMoved : 1;
uint isGLWidget : 1;
uint usesDoubleBufferedGLContext : 1;
uint inSetParent : 1;
// *************************** Platform specific ************************************

View file

@ -2789,7 +2789,6 @@ int QWidget::metric(PaintDeviceMetric m) const
void QWidgetPrivate::createSysExtra()
{
extra->compress_events = true;
extra->xDndProxy = 0;
}

View file

@ -1378,14 +1378,7 @@ void QWidgetPrivate::repaint_sys(const QRegion &rgn)
extra->staticContentsSize = data.crect.size();
}
QPaintEngine *engine = q->paintEngine();
// QGLWidget does not support partial updates if:
// 1) The context is double buffered
// 2) The context is single buffered and auto-fill background is enabled.
const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL
|| engine->type() == QPaintEngine::OpenGL2))
&& (usesDoubleBufferedGLContext || q->autoFillBackground());
QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn);
QRegion toBePainted(rgn);
toBePainted &= clipRect();
clipToEffectiveMask(toBePainted);

View file

@ -57,14 +57,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, graphicsloader,
QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
{
QGraphicsSystem *ret = 0;
QGraphicsSystem *ret = Q_NULLPTR;
QString system = key.toLower();
#if defined (QT_GRAPHICSSYSTEM_OPENGL)
if (system.isEmpty()) {
system = QLatin1String("opengl");
}
#elif defined (QT_GRAPHICSSYSTEM_RASTER) || defined(Q_WS_X11)
#if defined (QT_GRAPHICSSYSTEM_RASTER) || defined(Q_WS_X11)
if (system.isEmpty()) {
system = QLatin1String("raster");
}

View file

@ -153,11 +153,9 @@ QFont QTextItem::font() const
Qt 4.0 provides several premade implementations of QPaintEngine for the
different painter backends we support. We provide one paint engine for each
window system and painting framework we support. This includes X11 on
Unix/Linux and CoreGraphics on Mac OS X. In addition we provide QPaintEngine
implementations for OpenGL (accessible through QGLWidget) and PostScript
(accessible through QPSPrinter on X11). Additionally there is a raster-based
paint engine that is a fallback for when an engine does not support a certain
capability.
Unix/Linux. In addition we provide PostScript (accessible through
QPSPrinter on X11). Additionally there is a raster-based paint engine that
is a fallback for when an engine does not support a certain capability.
If one wants to use QPainter to draw to a different backend,
one must subclass QPaintEngine and reimplement all its virtual
@ -359,13 +357,11 @@ void QPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDraw
\value X11
\value PostScript
\value OpenGL
\value SVG Scalable Vector Graphics XML format
\value Raster
\value Pdf Portable Document Format
\value User First user type ID
\value MaxUser Last user type ID
\value OpenGL2
\value PaintBuffer
*/

View file

@ -184,12 +184,10 @@ public:
enum Type {
X11,
PostScript,
OpenGL,
Picture,
SVG,
Raster,
Pdf,
OpenGL2,
PaintBuffer,
User = 50, // first user type id

View file

@ -882,9 +882,6 @@ void QPainterPrivate::updateState(QPainterState *newState)
should antialias text if possible, and the \l
{RenderHint}{QPainter::SmoothPixmapTransform} indicates that the
engine should use a smooth pixmap transformation algorithm.
\l {RenderHint}{HighQualityAntialiasing} is an OpenGL-specific rendering hint
indicating that the engine should use fragment programs and offscreen
rendering for antialiasing.
The renderHints() function returns a flag that specifies the
rendering hints that are set for this painter. Use the
@ -1061,18 +1058,9 @@ void QPainterPrivate::updateState(QPainterState *newState)
only use the format types QImage::Format_ARGB32_Premultiplied,
QImage::Format_RGB32 or QImage::Format_RGB16. Any other format,
including QImage::Format_ARGB32, has significantly worse
performance. This engine is also used by default on Windows and on
QWS. It can be used as default graphics system on any
OS/hardware/software combination by passing \c {-graphicssystem
raster} on the command line
\o OpenGL 2.0 (ES) - This backend is the primary backend for
hardware accelerated graphics. It can be run on desktop machines
and embedded devices supporting the OpenGL 2.0 or OpenGL/ES 2.0
specification. This includes most graphics chips produced in the
last couple of years. The engine can be enabled by using QPainter
onto a QGLWidget or by passing \c {-graphicssystem opengl} on the
command line when the underlying system supports it.
performance. This engine is also used by default. It can be used
as default graphics system on any OS/hardware/software combination
by passing \c {-graphicssystem raster} on the command line
\endlist
@ -1133,10 +1121,6 @@ void QPainterPrivate::updateState(QPainterState *newState)
a smooth pixmap transformation algorithm (such as bilinear) rather
than nearest neighbor.
\value HighQualityAntialiasing An OpenGL-specific rendering hint
indicating that the engine should use fragment programs and offscreen
rendering for antialiasing.
\value NonCosmeticDefaultPen The engine should interpret pens with a width
of 0 (which otherwise enables QPen::isCosmetic()) as being a non-cosmetic
pen with a width of 1.
@ -1680,24 +1664,7 @@ QPaintEngine *QPainter::paintEngine() const
Note that only the states the underlying paint engine changes will be reset
to their respective default states. The states we reset may change from
release to release. The following states are currently reset in the OpenGL
2 engine:
\list
\i blending is disabled
\i the depth, stencil and scissor tests are disabled
\i the active texture unit is reset to 0
\i the depth mask, depth function and the clear depth are reset to their
default values
\i the stencil mask, stencil operation and stencil function are reset to
their default values
\i the current color is reset to solid white
\endlist
If, for example, the OpenGL polygon mode is changed by the user inside a
beginNativePaint()/endNativePainting() block, it will not be reset to the
default state by endNativePainting(). Here is an example that shows
intermixing of painter commands and raw OpenGL commands:
release to release.
\snippet doc/src/snippets/code/src_gui_painting_qpainter.cpp 21

View file

@ -91,8 +91,7 @@ public:
Antialiasing = 0x01,
TextAntialiasing = 0x02,
SmoothPixmapTransform = 0x04,
HighQualityAntialiasing = 0x08,
NonCosmeticDefaultPen = 0x10
NonCosmeticDefaultPen = 0x08
};
Q_DECLARE_FLAGS(RenderHints, RenderHint)
@ -468,7 +467,6 @@ private:
friend class QFontEngineXLFD;
friend class QPaintEngine;
friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
friend class QRasterPaintEngine;

View file

@ -1293,6 +1293,7 @@ QFont::StyleHint QFont::styleHint() const
\value System the font matcher prefers system fonts.
*/
#warning opengl leftovers
/*!
\enum QFont::StyleStrategy

View file

@ -127,10 +127,10 @@ QT_BEGIN_NAMESPACE
If it's the first time the static text is drawn, or if the static text, or the painter's font
has been altered since the last time it was drawn, the text's layout has to be
recalculated. On some paint engines, changing the matrix of the painter will also cause the
layout to be recalculated. In particular, this will happen for any engine except for the
OpenGL2 paint engine. Recalculating the layout will impose an overhead on the
QPainter::drawStaticText() call where it occurs. To avoid this overhead in the paint event, you
can call prepare() ahead of time to ensure that the layout is calculated.
layout to be recalculated. In particular, this will happen for any paint engine. Recalculating
the layout will impose an overhead on the QPainter::drawStaticText() call where it occurs. To
avoid this overhead in the paint event, you can call prepare() ahead of time to ensure that
the layout is calculated.
\sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
*/
@ -140,9 +140,7 @@ QT_BEGIN_NAMESPACE
This enum the different performance hints that can be set on the QStaticText. These hints
can be used to indicate that the QStaticText should use additional caches, if possible,
to improve performance at the expense of memory. In particular, setting the performance hint
AggressiveCaching on the QStaticText will improve performance when using the OpenGL graphics
system or when drawing to a QGLWidget.
to improve performance at the expense of memory.
\value ModerateCaching Do basic caching for high performance at a low memory cost.
\value AggressiveCaching Use additional caching when available. This may improve performance
@ -199,8 +197,8 @@ void QStaticText::detach()
When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
of the QStaticText object has changed since the last time it was drawn. It will also be
recalculated if the painter's font is not the same as when the QStaticText was last drawn, or,
on any other paint engine than the OpenGL2 engine, if the painter's matrix has been altered
since the static text was last drawn.
on any other paint engine, if the painter's matrix has been altered since the static text was
last drawn.
To avoid the overhead of creating the layout the first time you draw the QStaticText after
making changes, you can use the prepare() function and pass in the \a matrix and \a font you
@ -298,6 +296,7 @@ QString QStaticText::text() const
return data->text;
}
#warning opengl specific PerformanceHint
/*!
Sets the performance hint of the QStaticText according to the \a
performanceHint provided. The \a performanceHint is used to

View file

@ -63,16 +63,10 @@ QT_BEGIN_NAMESPACE
class QStaticTextUserData
{
public:
enum Type {
NoUserData,
OpenGLUserData
};
QStaticTextUserData(Type t) : type(t) { ref = 0; }
QStaticTextUserData() { ref = 0; }
virtual ~QStaticTextUserData() {}
QAtomicInt ref;
Type type;
};
class Q_GUI_EXPORT QStaticTextItem

View file

@ -12,23 +12,14 @@ include_directories(
${CMAKE_BINARY_DIR}/privateinclude/QtDeclarative
${CMAKE_BINARY_DIR}/include/QtScript
${CMAKE_BINARY_DIR}/privateinclude/QtScript
${CMAKE_BINARY_DIR}/include/QtOpenGL
${CMAKE_BINARY_DIR}/privateinclude/QtOpenGL
${CMAKE_CURRENT_SOURCE_DIR}/folderlistmodel
${CMAKE_CURRENT_SOURCE_DIR}/particles
${CMAKE_CURRENT_SOURCE_DIR}/gestures
${CMAKE_CURRENT_SOURCE_DIR}/shaders
${CMAKE_CURRENT_SOURCE_DIR}/shaders/scenegraph
${CMAKE_CURRENT_BINARY_DIR}/folderlistmodel
${CMAKE_CURRENT_BINARY_DIR}/particles
${CMAKE_CURRENT_BINARY_DIR}/gestures
${CMAKE_CURRENT_BINARY_DIR}/shaders
${CMAKE_CURRENT_BINARY_DIR}/shaders/scenegraph
)
include(folderlistmodel/folderlistmodel.cmake)
include(particles/particles.cmake)
include(gestures/gestures.cmake)
if(NOT WITH_OPENGLES1 AND OPENGL_FOUND)
include(shaders/shaders.cmake)
endif()

View file

@ -1,70 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef GLFUNCTIONS_H
#define GLFUNCTIONS_H
#ifndef QT_OPENGL_ES
#ifndef APIENTRYP
# ifdef APIENTRY
# define APIENTRYP APIENTRY *
# else
# define APIENTRY
# define APIENTRYP *
# endif
#endif
#define GL_TEXTURE0 0x84C0
#define GL_CLAMP_TO_EDGE 0x812F
#define GL_BGRA 0x80E1
typedef void (APIENTRYP type_glActiveTexture)(GLenum texture);
typedef void (APIENTRYP type_glGenerateMipmap)(GLenum target);
typedef void (APIENTRYP type_glVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
#define glActiveTexture ((type_glActiveTexture)QGLContext::currentContext()->getProcAddress(QLatin1String("glActiveTexture")))
#define glGenerateMipmap ((type_glGenerateMipmap)QGLContext::currentContext()->getProcAddress(QLatin1String("glGenerateMipmap")))
#define glVertexAttribPointer ((type_glVertexAttribPointer)QGLContext::currentContext()->getProcAddress(QLatin1String("glVertexAttribPointer")))
#endif
#endif // GLFUNCTIONS_H

View file

@ -1,2 +0,0 @@
plugin qmlshadersplugin

View file

@ -1,56 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qmlshadersplugin_plugin.h"
#include "shadereffectitem.h"
#include "shadereffectsource.h"
#include <QtDeclarative/qdeclarative.h>
void qmlshaderspluginPlugin::registerTypes(const char *uri)
{
qmlRegisterType<ShaderEffectItem>(uri, 1, 0, "ShaderEffectItem");
qmlRegisterType<ShaderEffectSource>(uri, 1, 0, "ShaderEffectSource");
}
Q_EXPORT_PLUGIN2(qmlshadersplugin, qmlshaderspluginPlugin)
#include <moc_qmlshadersplugin_plugin.h>

View file

@ -1,56 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QMLSHADERSPLUGIN_PLUGIN_H
#define QMLSHADERSPLUGIN_PLUGIN_H
#include <QtDeclarative/QDeclarativeExtensionPlugin>
class qmlshaderspluginPlugin : public QDeclarativeExtensionPlugin
{
Q_OBJECT
public:
void registerTypes(const char *uri);
};
#endif // QMLSHADERSPLUGIN_PLUGIN_H

View file

@ -1,194 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsggeometry.h"
QT_BEGIN_NAMESPACE
const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_Point2D()
{
static const Attribute data[] = {
{ 0, 2, GL_FLOAT }
};
static AttributeSet attrs = { 1, sizeof(float) * 2, data };
return attrs;
}
const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_TexturedPoint2D()
{
static const Attribute data[] = {
{ 0, 2, GL_FLOAT },
{ 1, 2, GL_FLOAT }
};
static AttributeSet attrs = { 2, sizeof(float) * 4, data };
return attrs;
}
const QSGGeometry::AttributeSet &QSGGeometry::defaultAttributes_ColoredPoint2D()
{
static const Attribute data[] = {
{ 0, 2, GL_FLOAT },
{ 1, 4, GL_UNSIGNED_BYTE }
};
static AttributeSet attrs = { 2, 2 * sizeof(float) + 4 * sizeof(char), data };
return attrs;
}
QSGGeometry::QSGGeometry(const QSGGeometry::AttributeSet &attributes,
int vertexCount,
int indexCount,
int indexType)
: m_drawing_mode(GL_TRIANGLE_STRIP)
, m_vertex_count(0)
, m_index_count(0)
, m_index_type(indexType)
, m_attributes(attributes)
, m_data(0)
, m_index_data_offset(-1)
, m_owns_data(false)
{
Q_ASSERT(m_attributes.count > 0);
Q_ASSERT(m_attributes.stride > 0);
// Because allocate reads m_vertex_count, m_index_count and m_owns_data, these
// need to be set before calling allocate...
allocate(vertexCount, indexCount);
}
QSGGeometry::~QSGGeometry()
{
if (m_owns_data)
free(m_data);
}
void *QSGGeometry::indexData()
{
return m_index_data_offset < 0
? 0
: ((char *) m_data + m_index_data_offset);
}
const void *QSGGeometry::indexData() const
{
return m_index_data_offset < 0
? 0
: ((char *) m_data + m_index_data_offset);
}
void QSGGeometry::setDrawingMode(GLenum mode)
{
m_drawing_mode = mode;
}
void QSGGeometry::allocate(int vertexCount, int indexCount)
{
if (vertexCount == m_vertex_count && indexCount == m_index_count)
return;
m_vertex_count = vertexCount;
m_index_count = indexCount;
bool canUsePrealloc = m_index_count <= 0;
int vertexByteSize = m_attributes.stride * m_vertex_count;
if (m_owns_data)
free(m_data);
if (canUsePrealloc && vertexByteSize <= (int) sizeof(m_prealloc)) {
m_data = (void *) &m_prealloc[0];
m_index_data_offset = -1;
m_owns_data = false;
} else {
Q_ASSERT(m_index_type == GL_UNSIGNED_INT || m_index_type == GL_UNSIGNED_SHORT);
int indexByteSize = indexCount * (m_index_type == GL_UNSIGNED_SHORT ? sizeof(quint16) : sizeof(quint32));
m_data = (void *) malloc(vertexByteSize + indexByteSize);
m_index_data_offset = vertexByteSize;
m_owns_data = true;
}
}
void QSGGeometry::updateRectGeometry(QSGGeometry *g, const QRectF &rect)
{
Point2D *v = g->vertexDataAsPoint2D();
v[0].x = rect.left();
v[0].y = rect.top();
v[1].x = rect.right();
v[1].y = rect.top();
v[2].x = rect.left();
v[2].y = rect.bottom();
v[3].x = rect.right();
v[3].y = rect.bottom();
}
void QSGGeometry::updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &textureRect)
{
TexturedPoint2D *v = g->vertexDataAsTexturedPoint2D();
v[0].x = rect.left();
v[0].y = rect.top();
v[0].tx = textureRect.left();
v[0].ty = textureRect.top();
v[1].x = rect.right();
v[1].y = rect.top();
v[1].tx = textureRect.right();
v[1].ty = textureRect.top();
v[2].x = rect.left();
v[2].y = rect.bottom();
v[2].tx = textureRect.left();
v[2].ty = textureRect.bottom();
v[3].x = rect.right();
v[3].y = rect.bottom();
v[3].tx = textureRect.right();
v[3].ty = textureRect.bottom();
}
QT_END_NAMESPACE

View file

@ -1,231 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSGGEOMETRY_H
#define QSGGEOMETRY_H
#include <QtOpenGL/qgl.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QSGGeometry
{
public:
struct Attribute
{
int position;
int tupleSize;
int type;
};
struct AttributeSet {
int count;
int stride;
const Attribute *attributes;
};
struct Point2D { float x, y; };
struct TexturedPoint2D { float x, y; float tx, ty; };
struct ColoredPoint2D { float x, y; unsigned char r, g, b, a; };
static const AttributeSet &defaultAttributes_Point2D();
static const AttributeSet &defaultAttributes_TexturedPoint2D();
static const AttributeSet &defaultAttributes_ColoredPoint2D();
QSGGeometry(const QSGGeometry::AttributeSet &attribs,
int vertexCount,
int indexCount = 0,
int indexType = GL_UNSIGNED_SHORT);
~QSGGeometry();
void setDrawingMode(GLenum mode);
inline GLenum drawingMode() const { return m_drawing_mode; }
void allocate(int vertexCount, int indexCount = 0);
int vertexCount() const { return m_vertex_count; }
void *vertexData() { return m_data; }
inline Point2D *vertexDataAsPoint2D();
inline TexturedPoint2D *vertexDataAsTexturedPoint2D();
inline ColoredPoint2D *vertexDataAsColoredPoint2D();
inline const void *vertexData() const { return m_data; }
inline const Point2D *vertexDataAsPoint2D() const;
inline const TexturedPoint2D *vertexDataAsTexturedPoint2D() const;
inline const ColoredPoint2D *vertexDataAsColoredPoint2D() const;
inline int indexType() const { return m_index_type; }
int indexCount() const { return m_index_count; }
void *indexData();
inline uint *indexDataAsUInt();
inline quint16 *indexDataAsUShort();
const void *indexData() const;
inline const uint *indexDataAsUInt() const;
inline const quint16 *indexDataAsUShort() const;
inline int attributeCount() const { return m_attributes.count; }
inline const Attribute *attributes() const { return m_attributes.attributes; }
inline int stride() const { return m_attributes.stride; }
static void updateRectGeometry(QSGGeometry *g, const QRectF &rect);
static void updateTexturedRectGeometry(QSGGeometry *g, const QRectF &rect, const QRectF &sourceRect);
private:
int m_drawing_mode;
int m_vertex_count;
int m_index_count;
int m_index_type;
const AttributeSet &m_attributes;
void *m_data;
int m_index_data_offset;
uint m_owns_data : 1;
float m_prealloc[16];
};
inline uint *QSGGeometry::indexDataAsUInt()
{
Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
return (uint *) indexData();
}
inline quint16 *QSGGeometry::indexDataAsUShort()
{
Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
return (quint16 *) indexData();
}
inline const uint *QSGGeometry::indexDataAsUInt() const
{
Q_ASSERT(m_index_type == GL_UNSIGNED_INT);
return (uint *) indexData();
}
inline const quint16 *QSGGeometry::indexDataAsUShort() const
{
Q_ASSERT(m_index_type == GL_UNSIGNED_SHORT);
return (quint16 *) indexData();
}
inline QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D()
{
Q_ASSERT(m_attributes.count == 1);
Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[0].position == 0);
return (Point2D *) m_data;
}
inline QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D()
{
Q_ASSERT(m_attributes.count == 2);
Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
Q_ASSERT(m_attributes.attributes[0].position == 0);
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[1].position == 1);
Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
return (TexturedPoint2D *) m_data;
}
inline QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D()
{
Q_ASSERT(m_attributes.count == 2);
Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
Q_ASSERT(m_attributes.attributes[0].position == 0);
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[1].position == 1);
Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
return (ColoredPoint2D *) m_data;
}
inline const QSGGeometry::Point2D *QSGGeometry::vertexDataAsPoint2D() const
{
Q_ASSERT(m_attributes.count == 1);
Q_ASSERT(m_attributes.stride == 2 * sizeof(float));
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[0].position == 0);
return (const Point2D *) m_data;
}
inline const QSGGeometry::TexturedPoint2D *QSGGeometry::vertexDataAsTexturedPoint2D() const
{
Q_ASSERT(m_attributes.count == 2);
Q_ASSERT(m_attributes.stride == 4 * sizeof(float));
Q_ASSERT(m_attributes.attributes[0].position == 0);
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[1].position == 1);
Q_ASSERT(m_attributes.attributes[1].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[1].type == GL_FLOAT);
return (const TexturedPoint2D *) m_data;
}
inline const QSGGeometry::ColoredPoint2D *QSGGeometry::vertexDataAsColoredPoint2D() const
{
Q_ASSERT(m_attributes.count == 2);
Q_ASSERT(m_attributes.stride == 2 * sizeof(float) + 4 * sizeof(char));
Q_ASSERT(m_attributes.attributes[0].position == 0);
Q_ASSERT(m_attributes.attributes[0].tupleSize == 2);
Q_ASSERT(m_attributes.attributes[0].type == GL_FLOAT);
Q_ASSERT(m_attributes.attributes[1].position == 1);
Q_ASSERT(m_attributes.attributes[1].tupleSize == 4);
Q_ASSERT(m_attributes.attributes[1].type == GL_UNSIGNED_BYTE);
return (const ColoredPoint2D *) m_data;
}
QT_END_NAMESPACE
QT_END_HEADER
#endif // QSGGEOMETRY_H

View file

@ -1,197 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "shadereffect.h"
#include "shadereffectbuffer.h"
#include "shadereffectsource.h"
#include <QDeclarativeItem>
#include <QPainter>
#include <QtOpenGL/qgl.h>
static QTransform savedWorldTransform;
ShaderEffect::ShaderEffect(QObject *parent)
: QGraphicsEffect(parent)
, m_changed(true)
{
}
ShaderEffect::~ShaderEffect()
{
}
void ShaderEffect::prepareBufferedDraw(QPainter *painter)
{
#ifndef QT_NO_DYNAMIC_CAST
// This workaround needed because QGraphicsEffect seems to always utilize default painters worldtransform
// instead of the active painters worldtransform.
const ShaderEffectBuffer *effectBuffer = dynamic_cast<ShaderEffectBuffer*> (painter->device());
if (effectBuffer) {
savedWorldTransform = painter->worldTransform() * savedWorldTransform;
painter->setWorldTransform(savedWorldTransform);
} else {
savedWorldTransform = painter->worldTransform();
}
#else
Q_UNUSED(painter);
#endif
}
void ShaderEffect::draw (QPainter *painter)
{
const QGLContext *context = QGLContext::currentContext();
prepareBufferedDraw(painter);
if (context) {
updateRenderTargets();
}
if (!context || m_renderTargets.count() == 0 || !hideOriginal())
drawSource(painter);
}
void ShaderEffect::updateRenderTargets()
{
if (!m_changed)
return;
m_changed = false;
int count = m_renderTargets.count();
for (int i = 0; i < count; i++) {
if (m_renderTargets[i]->isLive() || m_renderTargets[i]->isDirtyTexture()) {
m_renderTargets[i]->updateBackbuffer();
ShaderEffectBuffer* target = m_renderTargets[i]->fbo();
if (target && target->isValid() && target->width() > 0 && target->height() > 0) {
QPainter p(target);
p.setCompositionMode(QPainter::CompositionMode_Clear);
p.fillRect(QRect(QPoint(0, 0), target->size()), Qt::transparent);
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
QRectF sourceRect = m_renderTargets[i]->sourceRect();
QSize textureSize = m_renderTargets[i]->textureSize();
qreal yflip = m_renderTargets[i]->isMirrored() ? -1.0 : 1.0; // flip y to match scenegraph, it also flips texturecoordinates
qreal xscale = 1.0;
qreal yscale = 1.0 * yflip;
qreal leftMargin = 0.0;
qreal rightMargin = 0.0;
qreal topMargin = 0.0;
qreal bottomMargin = 0.0;
qreal width = m_renderTargets[i]->sourceItem()->width();
qreal height = m_renderTargets[i]->sourceItem()->height();
if (!sourceRect.isEmpty()) {
leftMargin = -sourceRect.left();
rightMargin = sourceRect.right() - width;
topMargin = -sourceRect.top();
bottomMargin = sourceRect.bottom() - height;
}
if ((width + leftMargin + rightMargin) > 0 && (height + topMargin + bottomMargin) > 0) {
if (!textureSize.isEmpty()) {
qreal textureWidth = textureSize.width();
qreal textureHeight = textureSize.height();
xscale = width / (width + leftMargin + rightMargin);
yscale = height / (height + topMargin + bottomMargin);
p.translate(textureWidth / 2, textureHeight / 2);
p.scale(xscale, yscale * yflip);
p.translate(-textureWidth / 2, -textureHeight / 2);
p.scale(textureWidth / width, textureHeight / height);
} else {
xscale = width / (width + leftMargin + rightMargin);
yscale = height / (height + topMargin + bottomMargin);
p.translate(width / 2, height / 2);
p.scale(xscale, yscale * yflip);
p.translate(-width / 2, -height / 2);
}
}
drawSource(&p);
p.end();
m_renderTargets[i]->markSceneGraphDirty();
}
}
}
}
void ShaderEffect::sourceChanged (ChangeFlags flags)
{
Q_UNUSED(flags);
m_changed = true;
}
void ShaderEffect::addRenderTarget(ShaderEffectSource *target)
{
if (!m_renderTargets.contains(target))
m_renderTargets.append(target);
}
void ShaderEffect::removeRenderTarget(ShaderEffectSource *target)
{
int index = m_renderTargets.indexOf(target);
if (index >= 0)
m_renderTargets.remove(index);
else
qWarning() << "ShaderEffect::removeRenderTarget - did not find target.";
}
bool ShaderEffect::hideOriginal() const
{
if (m_renderTargets.count() == 0)
return false;
// Just like scenegraph version, if there is even one source that says "hide original" we hide it.
int count = m_renderTargets.count();
for (int i = 0; i < count; i++) {
if (m_renderTargets[i]->hideSource())
return true;
}
return false;
}
#include <moc_shadereffect.h>

View file

@ -1,83 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SHADEREFFECT_H
#define SHADEREFFECT_H
#include <QPointer>
#include <QGraphicsEffect>
#include <QtOpenGL/qglframebufferobject.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class ShaderEffectSource;
class ShaderEffect : public QGraphicsEffect
{
Q_OBJECT
public:
ShaderEffect(QObject *parent = Q_NULLPTR);
~ShaderEffect();
void addRenderTarget(ShaderEffectSource *target);
void removeRenderTarget(ShaderEffectSource *target);
protected:
virtual void draw (QPainter *painter);
virtual void sourceChanged (ChangeFlags flags);
private:
void prepareBufferedDraw(QPainter *painter);
void updateRenderTargets();
bool hideOriginal() const;
public:
QVector<ShaderEffectSource*> m_renderTargets;
bool m_changed : 1;
};
QT_END_HEADER
QT_END_NAMESPACE
#endif // SHADEREFFECT_H

View file

@ -1,52 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "shadereffectbuffer.h"
ShaderEffectBuffer::ShaderEffectBuffer(const QSize & size, const QGLFramebufferObjectFormat & format)
: QGLFramebufferObject(size, format)
{
}
ShaderEffectBuffer::~ShaderEffectBuffer()
{
}

View file

@ -1,63 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SHADEREFFECTBUFFER_H
#define SHADEREFFECTBUFFER_H
#include <QtOpenGL/qglframebufferobject.h>
#include <QtOpenGL/qgl.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class ShaderEffectBuffer : public QGLFramebufferObject
{
public:
ShaderEffectBuffer(const QSize &size, const QGLFramebufferObjectFormat &format);
~ShaderEffectBuffer();
};
QT_END_HEADER
QT_END_NAMESPACE
#endif // SHADEREFFECTBUFFER_H

View file

@ -1,930 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "shadereffectitem.h"
#include "shadereffect.h"
#include "glfunctions.h"
#include <QtGui/qgraphicsview.h>
#include <QPainter>
#include <QtOpenGL/qgl.h>
static const char qt_default_vertex_code[] =
"uniform highp mat4 qt_ModelViewProjectionMatrix;\n"
"attribute highp vec4 qt_Vertex;\n"
"attribute highp vec2 qt_MultiTexCoord0;\n"
"varying highp vec2 qt_TexCoord0;\n"
"void main(void)\n"
"{\n"
"qt_TexCoord0 = qt_MultiTexCoord0;\n"
"gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;\n"
"}\n";
static const char qt_default_fragment_code[] =
"varying highp vec2 qt_TexCoord0;\n"
"uniform lowp sampler2D source;\n"
"void main(void)\n"
"{\n"
"gl_FragColor = texture2D(source, qt_TexCoord0.st);\n"
"}\n";
static const char qt_postion_attribute_name[] = "qt_Vertex";
static const char qt_texcoord_attribute_name[] = "qt_MultiTexCoord0";
static const char qt_emptyAttributeName[] = "";
/*!
\qmlclass ShaderEffectItem ShaderEffectItem
\ingroup qml-shader-elements
\brief The ShaderEffectItem object alters the output of given item with OpenGL shaders.
\inherits Item
ShaderEffectItem is available in the \bold{Qt.labs.shaders 1.0} module.
\e {Elements in the Qt.labs module are not guaranteed to remain compatible
in future versions.}
This element provides preliminary support for embedding OpenGL shader code into QML,
and may be heavily changed or removed in later versions.
Requirement for the use of shaders is that the application is either using
Qt OpenGL graphicssystem or is using OpenGL by setting QGLWidget as the viewport to QDeclarativeView (depending on which one is the recommened way in the targeted platform).
ShaderEffectItem internal behaviour is such that during the paint event it first renders its
ShaderEffectSource items into a OpenGL framebuffer object which can be used as a texture. If the ShaderEffectSource is defined to be an image,
it is directly uploaded as a texture. The texture(s) containing the source pixelcontent are then bound to graphics
pipeline texture units. Finally a textured mesh is passed to the vertex- and fragmentshaders which
then produce the final output for the ShaderEffectItem. It is possible to alter the mesh structure by defining
the amount vertices it contains, but currently it is not possible to import complex 3D-models to be used as the mesh.
It is possible to define one or more ShaderEffectItems to be a ShaderEffectSource for other ShaderEffectItems, but ShaderEffectItem
should never be declared as a child element of its source item(s) because it would cause circular loop in the painting.
A standard set of vertex attributes are provided for the shaders:
\list
\o qt_Vertex - The primary position of the vertex.
\o qt_MultiTexCoord0 - The texture co-ordinate at each vertex for texture unit 0.
\endlist
Additionally following uniforms are available for shaders:
\list
\o qt_Opacity - Effective opacity of the item.
\o qt_ModelViewProjectionMatrix - current 4x4 transformation matrix of the item.
\endlist
Furthermore, it is possible to utilize automatic QML propertybinding into vertex- and fragment shader
uniforms. Conversions are done according to the table below:
\table
\header
\o QML property
\o GLSL uniform
\row
\o property double foo: 1.0
\o uniform highp float foo
\row
\o property real foo: 1.0
\o uniform highp float foo
\row
\o property bool foo: true
\o uniform bool foo
\row
\o property int foo: 1
\o uniform int foo
\row
\o property variant foo: Qt.point(1,1)
\o uniform highp vec2 foo
\row
\o property variant foo: Qt.size(1, 1)
\o uniform highp vec2 foo
\row
\o property variant foo: Qt.rect(1, 1, 2, 2)
\o uniform highp vec4 foo
\row
\o property color foo: "#00000000"
\o uniform lowp vec4 foo
\row
\o property variant foo: Qt.vector3d(1.0, 2.0, 0.0)
\o uniform highp vec3 foo
\row
\o property variant foo: ShaderEffectSource { SourceItem: bar }
\o uniform lowp sampler2D foo
\endtable
\note
The uniform precision definitions in the above table are not strict, it is possible to choose the uniform
precision based on what is the most suitable for the shader code for that particular uniform.
The below example uses fragment shader to create simple wiggly effect to a text label.
Automatic property binding takes care of binding the properties to the uniforms if their
names are identical. ShaderEffectSource referring to textLabel is bound to sampler2D uniform inside the fragment
shader code.
\qml
import QtQuick 1.0
import Qt.labs.shaders 1.0
Rectangle {
width: 300
height: 300
color: "black"
Text {
id: textLabel
text: "Hello World"
anchors.centerIn: parent
font.pixelSize: 32
color: "white"
}
ShaderEffectItem {
property variant source: ShaderEffectSource { sourceItem: textLabel; hideSource: true }
property real wiggleAmount: 0.005
anchors.fill: textLabel
fragmentShader: "
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
uniform highp float wiggleAmount;
void main(void)
{
highp vec2 wiggledTexCoord = qt_TexCoord0;
wiggledTexCoord.s += sin(4.0 * 3.141592653589 * wiggledTexCoord.t) * wiggleAmount;
gl_FragColor = texture2D(source, wiggledTexCoord.st);
}
"
}
}
\endqml
\image shaderexample.png
*/
ShaderEffectItem::ShaderEffectItem(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
, m_program(0)
, m_meshResolution(1, 1)
, m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
, m_blending(true)
, m_program_dirty(true)
, m_active(true)
, m_respectsMatrix(false)
, m_respectsOpacity(false)
, m_checkedViewportUpdateMode(false)
, m_checkedOpenGL(false)
, m_checkedShaderPrograms(false)
, m_hasShaderPrograms(false)
, m_mirrored(false)
, m_defaultVertexShader(true)
{
setFlag(QGraphicsItem::ItemHasNoContents, false);
connect(this, SIGNAL(visibleChanged()), this, SLOT(handleVisibilityChange()));
m_active = isVisible();
}
ShaderEffectItem::~ShaderEffectItem()
{
reset();
}
/*!
\qmlproperty string ShaderEffectItem::fragmentShader
This property holds the OpenGL fragment shader code.
The default fragment shader is following:
\code
varying highp vec2 qt_TexCoord0;
uniform sampler2D source;
void main(void)
{
gl_FragColor = texture2D(source, qt_TexCoord0.st);
}
\endcode
*/
void ShaderEffectItem::setFragmentShader(const QString &code)
{
if (m_fragment_code.constData() == code.constData())
return;
m_fragment_code = code;
if (isComponentComplete()) {
reset();
updateProperties();
}
emit fragmentShaderChanged();
}
/*!
\qmlproperty string ShaderEffectItem::vertexShader
This property holds the OpenGL vertex shader code.
The default vertex shader is following:
\code
uniform highp mat4 qt_ModelViewProjectionMatrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 qt_TexCoord0;
void main(void)
{
qt_TexCoord0 = qt_MultiTexCoord0;
gl_Position = qt_ModelViewProjectionMatrix * qt_Vertex;
}
\endcode
*/
void ShaderEffectItem::setVertexShader(const QString &code)
{
if (m_vertex_code.constData() == code.constData())
return;
m_vertex_code = code;
m_defaultVertexShader = false;
if (isComponentComplete()) {
reset();
updateProperties();
}
emit vertexShaderChanged();
}
/*!
\qmlproperty bool ShaderEffectItem::blending
This property defines whether item is drawn using blending.
If true, the RGBA pixel output from the fragment shader is blended with
the pixel RGBA-values already in the framebuffer.
If false, fragment shader output is written to framebuffer as such.
Usually drawing without blending is slightly faster, thus disabling blending
might be a good choice when item is used as a background element.
\note
By default the pixel data in textures is stored in 32-bit premultiplied alpha format.
This should be taken into account when blending or reading the pixel values
in the fragment shader code.
The default value is true.
*/
void ShaderEffectItem::setBlending(bool enable)
{
if (m_blending == enable)
return;
m_blending = enable;
m_changed = true;
emit blendingChanged();
}
/*!
\qmlproperty QSize ShaderEffectItem::meshResolution
This property defines to how many triangles the item is divided into before its
vertices are passed to the vertex shader.
Triangles are defined as triangle strips and the amount of triangles can be controlled
separately for x and y-axis.
The default value is QSize(1,1).
*/
void ShaderEffectItem::setMeshResolution(const QSize &size)
{
if (size == m_meshResolution)
return;
m_meshResolution = size;
emit meshResolutionChanged();
updateGeometry();
}
void ShaderEffectItem::componentComplete()
{
updateProperties();
QDeclarativeItem::componentComplete();
}
void ShaderEffectItem::checkViewportUpdateMode()
{
if (!m_checkedViewportUpdateMode) {
QGraphicsScene *s = scene();
if (s){
QList<QGraphicsView*> views = s->views();
for (int i = 0; i < views.count(); i++) {
if (views[i]->viewportUpdateMode() != QGraphicsView::FullViewportUpdate) {
qWarning() << "ShaderEffectItem::checkViewportUpdateMode - consider setting QGraphicsView::FullViewportUpdate mode with OpenGL!";
}
}
}
m_checkedViewportUpdateMode = true;
}
}
void ShaderEffectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
if (!m_active) return;
const QGLContext *context = QGLContext::currentContext();
if (context) {
if (!m_checkedShaderPrograms) {
m_hasShaderPrograms = QGLShaderProgram::hasOpenGLShaderPrograms(context);
m_checkedShaderPrograms = true;
if (!m_hasShaderPrograms)
qWarning() << "ShaderEffectItem::paint - Shader programs are not supported";
}
if ( !m_hasShaderPrograms )
return;
checkViewportUpdateMode();
painter->save();
painter->beginNativePainting();
QMatrix4x4 combinedMatrix = QMatrix4x4(painter->transform());
renderEffect(painter, combinedMatrix);
painter->endNativePainting();
painter->restore();
} else {
if (!m_checkedOpenGL) {
qWarning() << "ShaderEffectItem::paint - OpenGL not available";
m_checkedOpenGL = true;
}
}
}
void ShaderEffectItem::renderEffect(QPainter *painter, const QMatrix4x4 &matrix)
{
if (!painter || !painter->device())
return;
if (!m_program || !m_program->programId()) {
// Deleted due to deactivation, to save GPU memory,
// or invalidated due to GL context change.
delete m_program;
if (QGLContext::currentContext())
m_program = new QGLShaderProgram(this);
if (!m_program)
qWarning() << "ShaderEffectItem::renderEffect - Creating QGLShaderProgram failed!";
}
if (!m_program)
return;
if (!m_program->isLinked() || m_program_dirty)
updateShaderProgram();
m_program->bind();
QMatrix4x4 combinedMatrix;
combinedMatrix.scale(2.0 / painter->device()->width(), -2.0 / painter->device()->height(), 1.0);
combinedMatrix.translate(-painter->device()->width() / 2.0, -painter->device()->height() / 2.0 );
combinedMatrix *= matrix;
updateEffectState(combinedMatrix);
for (int i = 0; i < m_attributeNames.size(); ++i) {
m_program->enableAttributeArray(m_geometry.attributes()[i].position);
}
bindGeometry();
// Optimization, disable depth test when we know we don't need it.
if (m_defaultVertexShader) {
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
} else {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_GREATER);
glDepthMask(true);
#if defined(QT_OPENGL_ES)
glClearDepthf(0);
#else
glClearDepth(0);
#endif
glClearColor(0, 0, 0, 0);
glClear(GL_DEPTH_BUFFER_BIT);
}
if (m_blending){
glEnable(GL_BLEND);
glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
} else {
glDisable(GL_BLEND);
}
if (m_geometry.indexCount())
glDrawElements(m_geometry.drawingMode(), m_geometry.indexCount(), m_geometry.indexType(), m_geometry.indexData());
else
glDrawArrays(m_geometry.drawingMode(), 0, m_geometry.vertexCount());
glDepthMask(false);
glDisable(GL_DEPTH_TEST);
for (int i = 0; i < m_attributeNames.size(); ++i)
m_program->disableAttributeArray(m_geometry.attributes()[i].position);
}
void ShaderEffectItem::updateEffectState(const QMatrix4x4 &matrix)
{
if (!m_program)
return;
for (int i = m_sources.size() - 1; i >= 0; --i) {
const ShaderEffectItem::SourceData &source = m_sources.at(i);
if (!source.source)
continue;
glActiveTexture(GL_TEXTURE0 + i);
source.source->bind();
}
if (m_respectsOpacity)
m_program->setUniformValue("qt_Opacity", static_cast<float> (effectiveOpacity()));
if (m_respectsMatrix){
m_program->setUniformValue("qt_ModelViewProjectionMatrix", matrix);
}
QSet<QByteArray>::const_iterator it;
for (it = m_uniformNames.begin(); it != m_uniformNames.end(); ++it) {
const QByteArray &name = *it;
QVariant v = property(name.constData());
switch (v.type()) {
case QVariant::Color:
m_program->setUniformValue(name.constData(), qvariant_cast<QColor>(v));
break;
case QVariant::Double:
m_program->setUniformValue(name.constData(), (float) qvariant_cast<double>(v));
break;
case QVariant::Transform:
m_program->setUniformValue(name.constData(), qvariant_cast<QTransform>(v));
break;
case QVariant::Int:
m_program->setUniformValue(name.constData(), GLint(v.toInt()));
break;
case QVariant::Bool:
m_program->setUniformValue(name.constData(), GLint(v.toBool()));
break;
case QVariant::Size:
case QVariant::SizeF:
m_program->setUniformValue(name.constData(), v.toSizeF());
break;
case QVariant::Point:
case QVariant::PointF:
m_program->setUniformValue(name.constData(), v.toPointF());
break;
case QVariant::Rect:
case QVariant::RectF:
{
QRectF r = v.toRectF();
m_program->setUniformValue(name.constData(), r.x(), r.y(), r.width(), r.height());
}
break;
case QVariant::Vector3D:
m_program->setUniformValue(name.constData(), qvariant_cast<QVector3D>(v));
break;
default:
break;
}
}
}
static inline int size_of_type(GLenum type)
{
static const int sizes[] = {
sizeof(char),
sizeof(unsigned char),
sizeof(short),
sizeof(unsigned short),
sizeof(int),
sizeof(unsigned int),
sizeof(float),
2,
3,
4,
sizeof(double)
};
return sizes[type - GL_BYTE];
}
void ShaderEffectItem::bindGeometry()
{
if (!m_program)
return;
char const *const *attrNames = m_attributeNames.constData();
int offset = 0;
for (int j = 0; j < m_attributeNames.size(); ++j) {
if (!*attrNames[j])
continue;
Q_ASSERT_X(j < m_geometry.attributeCount(), "ShaderEffectItem::bindGeometry()", "Geometry lacks attribute required by material");
const QSGGeometry::Attribute &a = m_geometry.attributes()[j];
Q_ASSERT_X(j == a.position, "ShaderEffectItem::bindGeometry()", "Geometry does not have continuous attribute positions");
#if defined(QT_OPENGL_ES_2)
GLboolean normalize = a.type != GL_FLOAT;
#else
GLboolean normalize = a.type != GL_FLOAT && a.type != GL_DOUBLE;
#endif
if (normalize)
qWarning() << "ShaderEffectItem::bindGeometry() - non supported attribute type!";
m_program->setAttributeArray(a.position, (GLfloat*) (((char*) m_geometry.vertexData()) + offset), a.tupleSize, m_geometry.stride());
//glVertexAttribPointer(a.position, a.tupleSize, a.type, normalize, m_geometry.stride(), (char *) m_geometry.vertexData() + offset);
offset += a.tupleSize * size_of_type(a.type);
}
}
void ShaderEffectItem::updateGeometry()
{
QRectF srcRect(0, 1, 1, -1);
if (m_mirrored)
srcRect = QRectF(0, 0, 1, 1);
QRectF dstRect = QRectF(0,0, width(), height());
int vmesh = m_meshResolution.height();
int hmesh = m_meshResolution.width();
QSGGeometry *g = &m_geometry;
if (vmesh == 1 && hmesh == 1) {
if (g->vertexCount() != 4)
g->allocate(4);
QSGGeometry::updateTexturedRectGeometry(g, dstRect, srcRect);
return;
}
g->allocate((vmesh + 1) * (hmesh + 1), vmesh * 2 * (hmesh + 2));
QSGGeometry::TexturedPoint2D *vdata = g->vertexDataAsTexturedPoint2D();
for (int iy = 0; iy <= vmesh; ++iy) {
float fy = iy / float(vmesh);
float y = float(dstRect.top()) + fy * float(dstRect.height());
float ty = float(srcRect.top()) + fy * float(srcRect.height());
for (int ix = 0; ix <= hmesh; ++ix) {
float fx = ix / float(hmesh);
vdata->x = float(dstRect.left()) + fx * float(dstRect.width());
vdata->y = y;
vdata->tx = float(srcRect.left()) + fx * float(srcRect.width());
vdata->ty = ty;
++vdata;
}
}
quint16 *indices = (quint16 *)g->indexDataAsUShort();
int i = 0;
for (int iy = 0; iy < vmesh; ++iy) {
*(indices++) = i + hmesh + 1;
for (int ix = 0; ix <= hmesh; ++ix, ++i) {
*(indices++) = i + hmesh + 1;
*(indices++) = i;
}
*(indices++) = i - 1;
}
}
void ShaderEffectItem::setActive(bool enable)
{
if (m_active == enable)
return;
if (m_active) {
for (int i = 0; i < m_sources.size(); ++i) {
ShaderEffectSource *source = m_sources.at(i).source;
if (!source)
continue;
disconnect(source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
source->derefFromEffectItem();
}
}
m_active = enable;
if (m_active) {
for (int i = 0; i < m_sources.size(); ++i) {
ShaderEffectSource *source = m_sources.at(i).source;
if (!source)
continue;
source->refFromEffectItem();
connect(source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
}
}
// QGLShaderProgram is deleted when not active (to minimize GPU memory usage).
if (!m_active && m_program) {
delete m_program;
m_program = 0;
}
emit activeChanged();
markDirty();
}
void ShaderEffectItem::preprocess()
{
for (int i = 0; i < m_sources.size(); ++i) {
ShaderEffectSource *source = m_sources.at(i).source;
if (source)
source->updateBackbuffer();
}
}
void ShaderEffectItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
if (newGeometry.size() != oldGeometry.size())
updateGeometry();
QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
}
void ShaderEffectItem::changeSource(int index)
{
Q_ASSERT(index >= 0 && index < m_sources.size());
QVariant v = property(m_sources.at(index).name.constData());
setSource(v, index);
}
void ShaderEffectItem::markDirty() {
update();
}
void ShaderEffectItem::setSource(const QVariant &var, int index)
{
Q_ASSERT(index >= 0 && index < m_sources.size());
SourceData &source = m_sources[index];
source.source = 0;
source.item = 0;
if (var.isNull()) {
return;
}
QObject *obj = qvariant_cast<QObject *>(var);
if (!obj) {
qWarning("Could not assign source of type '%s' to property '%s'.", var.typeName(), source.name.constData());
return;
}
source.source = qobject_cast<ShaderEffectSource *>(obj);
source.item = qobject_cast<QDeclarativeItem *>(obj);
if (!source.item)
qWarning("Could not assign property '%s', did not implement QDeclarativeItem.", source.name.constData());
if (!source.source)
qWarning("Could not assign property '%s', did not implement ShaderEffectSource.", source.name.constData());
// TODO: Find better solution.
// 'source.item' needs a canvas to get a scenegraph node.
// The easiest way to make sure it gets a canvas is to
// make it a part of the same item tree as 'this'.
if (source.item && source.item->parentItem() == 0) {
source.item->setParentItem(this);
// Unlike in scenegraph, we cannot set item invisible here because qgraphicsview would optimize it away.
}
// Unlike in scenegraph, ref counting is used to optimize memory consumption. Sources themself may free fbos when not referenced.
if (m_active && source.source) {
source.source->refFromEffectItem();
connect(source.source, SIGNAL(repaintRequired()), this, SLOT(markDirty()));
}
}
void ShaderEffectItem::disconnectPropertySignals()
{
disconnect(this, 0, this, SLOT(markDirty()));
for (int i = 0; i < m_sources.size(); ++i) {
SourceData &source = m_sources[i];
disconnect(this, 0, source.mapper, 0);
disconnect(source.mapper, 0, this, 0);
}
}
void ShaderEffectItem::connectPropertySignals()
{
QSet<QByteArray>::const_iterator it;
for (it = m_uniformNames.begin(); it != m_uniformNames.end(); ++it) {
int pi = metaObject()->indexOfProperty(it->constData());
if (pi >= 0) {
QMetaProperty mp = metaObject()->property(pi);
if (!mp.hasNotifySignal())
qWarning("ShaderEffectItem: property '%s' does not have notification method!", it->constData());
QByteArray signalName("2");
signalName.append(mp.notifySignal().signature());
connect(this, signalName, this, SLOT(markDirty()));
} else {
qWarning("ShaderEffectItem: '%s' does not have a matching property!", it->constData());
}
}
for (int i = 0; i < m_sources.size(); ++i) {
SourceData &source = m_sources[i];
int pi = metaObject()->indexOfProperty(source.name.constData());
if (pi >= 0) {
QMetaProperty mp = metaObject()->property(pi);
QByteArray signalName("2");
signalName.append(mp.notifySignal().signature());
connect(this, signalName, source.mapper, SLOT(map()));
source.mapper->setMapping(this, i);
connect(source.mapper, SIGNAL(mapped(int)), this, SLOT(changeSource(int)));
} else {
qWarning("ShaderEffectItem: '%s' does not have a matching source!", source.name.constData());
}
}
}
void ShaderEffectItem::reset()
{
disconnectPropertySignals();
if (m_program)
m_program->removeAllShaders();
m_attributeNames.clear();
m_uniformNames.clear();
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
if (m_active && source.source)
source.source->derefFromEffectItem();
delete source.mapper;
}
m_sources.clear();
m_program_dirty = true;
}
void ShaderEffectItem::updateProperties()
{
QString vertexCode = m_vertex_code;
QString fragmentCode = m_fragment_code;
if (vertexCode.isEmpty())
vertexCode = QString::fromLatin1(qt_default_vertex_code);
if (fragmentCode.isEmpty())
fragmentCode = QString::fromLatin1(qt_default_fragment_code);
lookThroughShaderCode(vertexCode);
lookThroughShaderCode(fragmentCode);
if (!m_attributeNames.contains(qt_postion_attribute_name))
qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_postion_attribute_name);
if (!m_attributeNames.contains(qt_texcoord_attribute_name))
qWarning("ShaderEffectItem: Missing reference to \'%s\'.", qt_texcoord_attribute_name);
if (!m_respectsMatrix)
qWarning("ShaderEffectItem: Missing reference to \'qt_ModelViewProjectionMatrix\'.");
for (int i = 0; i < m_sources.size(); ++i) {
QVariant v = property(m_sources.at(i).name);
setSource(v, i); // Property exists.
}
connectPropertySignals();
}
void ShaderEffectItem::updateShaderProgram()
{
if (!m_program)
return;
QString vertexCode = m_vertex_code;
QString fragmentCode = m_fragment_code;
if (vertexCode.isEmpty())
vertexCode = QString::fromLatin1(qt_default_vertex_code);
if (fragmentCode.isEmpty())
fragmentCode = QString::fromLatin1(qt_default_fragment_code);
m_program->addShaderFromSourceCode(QGLShader::Vertex, vertexCode);
m_program->addShaderFromSourceCode(QGLShader::Fragment, fragmentCode);
for (int i = 0; i < m_attributeNames.size(); ++i) {
m_program->bindAttributeLocation(m_attributeNames.at(i), m_geometry.attributes()[i].position);
}
if (!m_program->link()) {
qWarning("ShaderEffectItem: Shader compilation failed:");
qWarning() << m_program->log();
}
if (!m_attributeNames.contains(qt_postion_attribute_name))
qWarning("ShaderEffectItem: Missing reference to \'qt_Vertex\'.");
if (!m_attributeNames.contains(qt_texcoord_attribute_name))
qWarning("ShaderEffectItem: Missing reference to \'qt_MultiTexCoord0\'.");
if (!m_respectsMatrix)
qWarning("ShaderEffectItem: Missing reference to \'qt_ModelViewProjectionMatrix\'.");
if (m_program->isLinked()) {
m_program->bind();
for (int i = 0; i < m_sources.size(); ++i)
m_program->setUniformValue(m_sources.at(i).name.constData(), (GLint) i);
}
m_program_dirty = false;
}
void ShaderEffectItem::lookThroughShaderCode(const QString &code)
{
// Regexp for matching attributes and uniforms.
// In human readable form: attribute|uniform [lowp|mediump|highp] <type> <name>
static QRegExp re(QLatin1String("\\b(attribute|uniform)\\b\\s*\\b(?:lowp|mediump|highp)?\\b\\s*\\b(\\w+)\\b\\s*\\b(\\w+)"));
Q_ASSERT(re.isValid());
int pos = -1;
//QString wideCode = QString::fromLatin1(code.constData(), code.size());
QString wideCode = code;
while ((pos = re.indexIn(wideCode, pos + 1)) != -1) {
QByteArray decl = re.cap(1).toLatin1(); // uniform or attribute
QByteArray type = re.cap(2).toLatin1(); // type
QByteArray name = re.cap(3).toLatin1(); // variable name
if (decl == "attribute") {
if (name == qt_postion_attribute_name) {
m_attributeNames.insert(0, qt_postion_attribute_name);
} else if (name == "qt_MultiTexCoord0") {
if (m_attributeNames.at(0) == 0) {
m_attributeNames.insert(0, qt_emptyAttributeName);
}
m_attributeNames.insert(1, qt_texcoord_attribute_name);
} else {
// TODO: Support user defined attributes.
qWarning("ShaderEffectItem: Attribute \'%s\' not recognized.", name.constData());
}
} else {
Q_ASSERT(decl == "uniform");
if (name == "qt_ModelViewProjectionMatrix") {
m_respectsMatrix = true;
} else if (name == "qt_Opacity") {
m_respectsOpacity = true;
} else {
m_uniformNames.insert(name);
if (type == "sampler2D") {
SourceData d;
d.mapper = new QSignalMapper;
d.source = 0;
d.name = name;
d.item = 0;
m_sources.append(d);
}
}
}
}
}
void ShaderEffectItem::handleVisibilityChange()
{
setActive(isVisible());
}
#include <moc_shadereffectitem.h>

View file

@ -1,155 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SHADEREFFECTITEM_H
#define SHADEREFFECTITEM_H
#include <QDeclarativeItem>
#include <QtOpenGL/qgl.h>
#include <QtOpenGL/qglshaderprogram.h>
#include <QtCore/qsignalmapper.h>
#include "shadereffectsource.h"
#include "scenegraph/qsggeometry.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class ShaderEffectItem : public QDeclarativeItem
{
Q_OBJECT
Q_INTERFACES(QDeclarativeParserStatus)
Q_PROPERTY(QString fragmentShader READ fragmentShader WRITE setFragmentShader NOTIFY fragmentShaderChanged)
Q_PROPERTY(QString vertexShader READ vertexShader WRITE setVertexShader NOTIFY vertexShaderChanged)
Q_PROPERTY(bool blending READ blending WRITE setBlending NOTIFY blendingChanged)
Q_PROPERTY(QSize meshResolution READ meshResolution WRITE setMeshResolution NOTIFY meshResolutionChanged)
public:
ShaderEffectItem(QDeclarativeItem* parent = 0);
~ShaderEffectItem();
virtual void componentComplete();
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
QString fragmentShader() const { return m_fragment_code; }
void setFragmentShader(const QString &code);
QString vertexShader() const { return m_vertex_code; }
void setVertexShader(const QString &code);
bool blending() const { return m_blending; }
void setBlending(bool enable);
QSize meshResolution() const { return m_meshResolution; }
void setMeshResolution(const QSize &size);
void preprocess();
Q_SIGNALS:
void fragmentShaderChanged();
void vertexShaderChanged();
void blendingChanged();
void activeChanged();
void meshResolutionChanged();
protected:
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
private Q_SLOTS:
void changeSource(int index);
void handleVisibilityChange();
void markDirty();
private:
void checkViewportUpdateMode();
void renderEffect(QPainter *painter, const QMatrix4x4 &matrix);
void updateEffectState(const QMatrix4x4 &matrix);
void updateGeometry();
void bindGeometry();
void setSource(const QVariant &var, int index);
void disconnectPropertySignals();
void connectPropertySignals();
void reset();
void updateProperties();
void updateShaderProgram();
void lookThroughShaderCode(const QString &code);
bool active() const { return m_active; }
void setActive(bool enable);
private:
QString m_fragment_code;
QString m_vertex_code;
QGLShaderProgram* m_program;
QVector<const char *> m_attributeNames;
QSet<QByteArray> m_uniformNames;
QSize m_meshResolution;
QSGGeometry m_geometry;
struct SourceData
{
QSignalMapper *mapper;
QPointer<ShaderEffectSource> source;
QPointer<QDeclarativeItem> item;
QByteArray name;
};
QVector<SourceData> m_sources;
bool m_changed : 1;
bool m_blending : 1;
bool m_program_dirty : 1;
bool m_active : 1;
bool m_respectsMatrix : 1;
bool m_respectsOpacity : 1;
bool m_checkedViewportUpdateMode : 1;
bool m_checkedOpenGL : 1;
bool m_checkedShaderPrograms : 1;
bool m_hasShaderPrograms : 1;
bool m_mirrored : 1;
bool m_defaultVertexShader : 1;
};
QT_END_HEADER
QT_END_NAMESPACE
#endif // SHADEREFFECTITEM_H

View file

@ -1,450 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "shadereffectsource.h"
#include "shadereffectbuffer.h"
#include "shadereffect.h"
#include "glfunctions.h"
#include <QtOpenGL/qglframebufferobject.h>
/*!
\qmlclass ShaderEffectSource ShaderEffectSource
\ingroup qml-shader-elements
\brief The ShaderEffectSource object encapsulates the source content for the ShaderEffectItem.
ShaderEffectSource is available in the \bold{Qt.labs.shaders 1.0} module.
\e {Elements in the Qt.labs module are not guaranteed to remain compatible
in future versions.}
This element provides preliminary support for OpenGL shaders in QML,
and may be heavily changed or removed in later versions.
Requirement for the ability to use of shaders is that the application is either using
opengl graphicssystem or has set QGLWidget as the viewport to QDeclarativeView (recommended way).
ShaderEffectSource object encapsulates the source content so that it can be utilized in ShaderEffectItem.
Source content can be a live QML object tree, or a snapshot of QML object tree.
*/
ShaderEffectSource::ShaderEffectSource(QDeclarativeItem *parent)
: QDeclarativeItem(parent)
, m_sourceItem(0)
, m_wrapMode(ClampToEdge)
, m_sourceRect(0, 0, 0, 0)
, m_textureSize(0, 0)
, m_format(RGBA)
, m_size(0, 0)
, m_fbo(0)
, m_multisampledFbo(0)
, m_refs(0)
, m_dirtyTexture(true)
, m_dirtySceneGraph(true)
, m_live(true)
, m_hideSource(false)
, m_mirrored(false)
{
}
ShaderEffectSource::~ShaderEffectSource()
{
if (m_refs && m_sourceItem)
detachSourceItem();
delete m_fbo;
delete m_multisampledFbo;
}
/*!
\qmlproperty Item ShaderEffectSource::sourceItem
This property holds the Item which is used as the source for the shader effect.
If the item has children, those are included as well.
\note When source item content is passed to the ShaderEffectItem(s), it is always clipped to the boundingrect of the
sourceItem regardless of its clipping property.
*/
void ShaderEffectSource::setSourceItem(QDeclarativeItem *item)
{
if (item == m_sourceItem)
return;
if (m_sourceItem) {
disconnect(m_sourceItem, SIGNAL(widthChanged()), this, SLOT(markSourceSizeDirty()));
disconnect(m_sourceItem, SIGNAL(heightChanged()), this, SLOT(markSourceSizeDirty()));
if (m_refs)
detachSourceItem();
}
m_sourceItem = item;
if (m_sourceItem) {
// Must have some item as parent
if (m_sourceItem->parentItem() == 0)
m_sourceItem->setParentItem(this);
if (m_refs)
attachSourceItem();
connect(m_sourceItem, SIGNAL(widthChanged()), this, SLOT(markSourceSizeDirty()));
connect(m_sourceItem, SIGNAL(heightChanged()), this, SLOT(markSourceSizeDirty()));
}
updateSizeAndTexture();
emit sourceItemChanged();
emit repaintRequired();
}
/*!
\qmlproperty QRectF ShaderEffectSource::sourceRect
This property can be used to specify margins for the source content.
If other value than Qt.rect(0,0,0,0) is assigned to this property, it is interpreted as
specifying a relative source rectangle for the source content.
For example, setting Qt.rect(-10.0, -10.0, 120.0, 120.0) for a source that has width and height
of 100 pixels would produce 10 pixels margins to each side of the source.
Margins are useful when the original content is wanted to be spread outside the original source area,
like when creating a dropshadow with the shader or in other similar effects.
The default value is Qt.rect(0,0,0,0).
*/
void ShaderEffectSource::setSourceRect(const QRectF &rect)
{
if (rect == m_sourceRect)
return;
m_sourceRect = rect;
updateSizeAndTexture();
emit sourceRectChanged();
emit repaintRequired();
m_dirtyTexture = true;
markSourceItemDirty();
}
/*!
\qmlproperty QSize ShaderEffectSource::textureSize
This property holds the size for the texture containing the source content.
If value QSize(0,0) is assigned to this property, texture is resized
according to the source size. Otherwise source content is scaled to
the given size.
The default value is QSize(0,0).
*/
void ShaderEffectSource::setTextureSize(const QSize &size)
{
if (size == m_textureSize)
return;
m_textureSize = size;
updateSizeAndTexture();
emit textureSizeChanged();
emit repaintRequired();
m_dirtyTexture = true;
markSourceItemDirty();
}
/*!
\qmlproperty bool ShaderEffectSource::live
This property holds the optimization flag to define whether the source item content is changing or
static.
If value true is assigned to this property, source item content is re-rendered into a
texture for every frame. Setting the value to false improves the performance as it skips
rendering the source item (and its chidleren) and instead immediately passes the previously
rendered and cached texture to the shaders.
The default value is true.
*/
void ShaderEffectSource::setLive(bool s)
{
if (s == m_live)
return;
m_live = s;
emit liveChanged();
emit repaintRequired();
}
/*!
\qmlproperty bool ShaderEffectSource::hideSource
This property holds the flag to define whether the original source item is
hidden when the effect item is drawn.
The default value is false.
*/
void ShaderEffectSource::setHideSource(bool hide)
{
if (hide == m_hideSource)
return;
m_hideSource = hide;
emit hideSourceChanged();
emit repaintRequired();
}
/*!
\qmlproperty enumeration ShaderEffectSource::wrapMode
This property defines the wrap parameter for the source after it has been mapped as a texture.
\list
\o ShaderEffectSource.ClampToEdge - Causes texturecoordinates to be clamped to the range [ 1/2*N , 1 - 1/2*N ], where N is the texture width.
\o ShaderEffectSource.RepeatHorizontally - Causes the integer part of the horizontal texturecoordinate to be ignored; the GL uses only the fractional part, thereby creating a horizontal repeating pattern.
\o ShaderEffectSource.RepeatVertically - Causes the integer part of the vertical texturecoordinate to be ignored; the GL uses only the fractional part, thereby creating a vertical repeating pattern.
\o ShaderEffectSource.Repeat - Causes the integer part of both the horizontal and vertical texturecoordinates to be ignored; the GL uses only the fractional part, thereby creating a repeating pattern.
\endlist
The default value is ClampToEdge.
*/
void ShaderEffectSource::setWrapMode(WrapMode mode)
{
if (mode == m_wrapMode)
return;
m_wrapMode = mode;
emit wrapModeChanged();
m_dirtyTexture = true;
markSourceItemDirty();
}
/*!
\qmlmethod ShaderEffectSource::grab()
Repaints the source item content into the texture.
This method is useful when ShaderEffectSource::live has been set to false and
the changes in the source item content is desired to be made visible for the shaders.
*/
void ShaderEffectSource::grab()
{
m_dirtyTexture = true;
emit repaintRequired();
}
void ShaderEffectSource::bind()
{
GLint filtering = smooth() ? GL_LINEAR : GL_NEAREST;
GLuint hwrap = (m_wrapMode == Repeat || m_wrapMode == RepeatHorizontally) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
GLuint vwrap = (m_wrapMode == Repeat || m_wrapMode == RepeatVertically) ? GL_REPEAT : GL_CLAMP_TO_EDGE;
#if !defined(QT_OPENGL_ES_2)
glEnable(GL_TEXTURE_2D);
#endif
if (m_fbo && m_fbo->isValid()) {
glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
} else {
m_dirtyTexture = true;
emit repaintRequired();
markSourceItemDirty();
glBindTexture(GL_TEXTURE_2D, 0);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, smooth() ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, hwrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, vwrap);
}
void ShaderEffectSource::refFromEffectItem()
{
if (m_refs++ == 0) {
attachSourceItem();
emit activeChanged();
}
}
void ShaderEffectSource::derefFromEffectItem()
{
if (--m_refs == 0) {
detachSourceItem();
emit activeChanged();
}
Q_ASSERT(m_refs >= 0);
}
void ShaderEffectSource::updateBackbuffer()
{
if (!m_sourceItem || !QGLContext::currentContext())
return;
// Multisampling is not (for now) supported.
QSize size = QSize(m_sourceItem->width(), m_sourceItem->height());
if (!m_textureSize.isEmpty())
size = m_textureSize;
if (size.height() > 0 && size.width() > 0) {
QGLFramebufferObjectFormat format;
format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(m_format);
if (!m_fbo) {
m_fbo = new ShaderEffectBuffer(size, format);
} else {
if (!m_fbo->isValid() || m_fbo->size() != size || m_fbo->format().internalTextureFormat() != GLenum(m_format)) {
delete m_fbo;
m_fbo = 0;
m_fbo = new ShaderEffectBuffer(size, format);
}
}
}
// Note that real update for the source content happens in shadereffect.cpp
m_dirtyTexture = false;
}
void ShaderEffectSource::markSceneGraphDirty()
{
m_dirtySceneGraph = true;
emit repaintRequired();
}
void ShaderEffectSource::markSourceSizeDirty()
{
Q_ASSERT(m_sourceItem);
if (m_textureSize.isEmpty())
updateSizeAndTexture();
if (m_refs)
emit repaintRequired();
}
void ShaderEffectSource::markSourceItemDirty()
{
m_dirtyTexture = true;
if (m_sourceItem) {
ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
if (effect)
effect->m_changed = true;
}
}
void ShaderEffectSource::updateSizeAndTexture()
{
if (m_sourceItem) {
QSize size = m_textureSize;
if (size.isEmpty())
size = QSize(m_sourceItem->width(), m_sourceItem->height());
if (size.width() < 1)
size.setWidth(1);
if (size.height() < 1)
size.setHeight(1);
if (m_fbo && (m_fbo->size() != size || !m_fbo->isValid())) {
delete m_fbo;
m_fbo = 0;
delete m_multisampledFbo;
m_fbo = m_multisampledFbo = 0;
}
if (m_size.width() != size.width()) {
m_size.setWidth(size.width());
emit widthChanged();
}
if (m_size.height() != size.height()) {
m_size.setHeight(size.height());
emit heightChanged();
}
m_dirtyTexture = true;
} else {
if (m_size.width() != 0) {
m_size.setWidth(0);
emit widthChanged();
}
if (m_size.height() != 0) {
m_size.setHeight(0);
emit heightChanged();
}
}
}
void ShaderEffectSource::attachSourceItem()
{
if (!m_sourceItem)
return;
ShaderEffect *effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
if (!effect) {
effect = new ShaderEffect();
m_sourceItem->setGraphicsEffect(effect);
}
if (effect)
effect->addRenderTarget(this);
m_sourceItem->update();
}
void ShaderEffectSource::detachSourceItem()
{
if (!m_sourceItem)
return;
ShaderEffect* effect = qobject_cast<ShaderEffect*> (m_sourceItem->graphicsEffect());
if (effect)
effect->removeRenderTarget(this);
delete m_fbo;
m_fbo = 0;
delete m_multisampledFbo;
m_multisampledFbo = 0;
m_dirtyTexture = true;
}
#include <moc_shadereffectsource.h>

View file

@ -1,158 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QML Shaders plugin of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef SHADEREFFECTSOURCE_H
#define SHADEREFFECTSOURCE_H
#include <QPointer>
#include <QDeclarativeItem>
#include <QtOpenGL/qgl.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class ShaderEffectBuffer;
class ShaderEffectSource : public QDeclarativeItem
{
Q_OBJECT
Q_PROPERTY(QDeclarativeItem *sourceItem READ sourceItem WRITE setSourceItem NOTIFY sourceItemChanged)
Q_PROPERTY(QRectF sourceRect READ sourceRect WRITE setSourceRect NOTIFY sourceRectChanged)
Q_PROPERTY(QSize textureSize READ textureSize WRITE setTextureSize NOTIFY textureSizeChanged)
Q_PROPERTY(bool live READ isLive WRITE setLive NOTIFY liveChanged)
Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged)
Q_ENUMS(WrapMode)
Q_ENUMS(Format)
public:
enum WrapMode {
ClampToEdge,
RepeatHorizontally,
RepeatVertically,
Repeat
};
enum Format {
Alpha = GL_ALPHA,
RGB = GL_RGB,
RGBA = GL_RGBA
};
ShaderEffectSource(QDeclarativeItem *parent = 0);
virtual ~ShaderEffectSource();
QDeclarativeItem *sourceItem() const { return m_sourceItem.data(); }
void setSourceItem(QDeclarativeItem *item);
QRectF sourceRect() const { return m_sourceRect; };
void setSourceRect(const QRectF &rect);
QSize textureSize() const { return m_textureSize; }
void setTextureSize(const QSize &size);
bool isLive() const { return m_live; }
void setLive(bool s);
bool hideSource() const { return m_hideSource; }
void setHideSource(bool hide);
WrapMode wrapMode() const { return m_wrapMode; };
void setWrapMode(WrapMode mode);
bool isActive() const { return m_refs; }
void bind();
void refFromEffectItem();
void derefFromEffectItem();
void updateBackbuffer();
ShaderEffectBuffer* fbo() { return m_fbo; }
bool isDirtyTexture() { return m_dirtyTexture; }
bool isMirrored() { return m_mirrored; }
Q_INVOKABLE void grab();
Q_SIGNALS:
void sourceItemChanged();
void sourceRectChanged();
void textureSizeChanged();
void formatChanged();
void liveChanged();
void hideSourceChanged();
void activeChanged();
void repaintRequired();
void wrapModeChanged();
public Q_SLOTS:
void markSceneGraphDirty();
void markSourceSizeDirty();
void markSourceItemDirty();
private:
void updateSizeAndTexture();
void attachSourceItem();
void detachSourceItem();
private:
QPointer<QDeclarativeItem> m_sourceItem;
WrapMode m_wrapMode;
QRectF m_sourceRect;
QSize m_textureSize;
Format m_format;
QSize m_size;
ShaderEffectBuffer *m_fbo;
ShaderEffectBuffer *m_multisampledFbo;
int m_refs;
bool m_dirtyTexture : 1;
bool m_dirtySceneGraph : 1;
bool m_live : 1;
bool m_hideSource : 1;
bool m_mirrored : 1;
};
QT_END_HEADER
QT_END_NAMESPACE
#endif // SHADEREFFECTSOURCE_H

View file

@ -1,37 +0,0 @@
# add_definitions()
set(EXTRA_SHADERS_LIBS KtOpenGL KtDeclarative)
set(SHADERS_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/shaders/qmlshadersplugin_plugin.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffect.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectitem.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectsource.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shaders/scenegraph/qsggeometry.cpp
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectbuffer.cpp
)
set(SHADERS_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/shaders/qmlshadersplugin_plugin.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/glfunctions.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffect.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectitem.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectsource.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/scenegraph/qsggeometry.h
${CMAKE_CURRENT_SOURCE_DIR}/shaders/shadereffectbuffer.h
)
include_directories(${OPENGL_INCLUDE_DIR})
katie_setup_target(qmlshadersplugin ${SHADERS_SOURCES} ${SHADERS_HEADERS})
add_library(qmlshadersplugin ${KATIE_TYPE} ${qmlshadersplugin_SOURCES})
target_link_libraries(qmlshadersplugin ${EXTRA_SHADERS_LIBS})
install(
TARGETS qmlshadersplugin
DESTINATION ${KATIE_IMPORTS_RELATIVE}/Qt/labs/shaders
)
install(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/shaders/qmldir
DESTINATION ${KATIE_IMPORTS_RELATIVE}/Qt/labs/shaders
)

View file

@ -1,191 +0,0 @@
add_definitions(-DQT_BUILD_OPENGL_LIB)
set(EXTRA_OPENGL_LIBS KtCore KtGui ${OPENGL_LIBRARIES})
set(OPENGL_PUBLIC_HEADERS
QGL
QGLBuffer
QGLColormap
QGLContext
QGLFormat
QGLFramebufferObject
QGLFramebufferObjectFormat
QGLFunctions
QGLFunctionsPrivate
QGLPixelBuffer
QGLScreen
QGLScreenSurfaceFunctions
QGLShader
QGLShaderProgram
QGLWidget
)
set(OPENGL_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/qgl.h
${CMAKE_CURRENT_SOURCE_DIR}/qgl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qglcolormap.h
${CMAKE_CURRENT_SOURCE_DIR}/qglpixelbuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/qglpixelbuffer_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qglframebufferobject.h
${CMAKE_CURRENT_SOURCE_DIR}/qglframebufferobject_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qglextensions_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qglpaintdevice_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qglbuffer.h
${CMAKE_CURRENT_SOURCE_DIR}/qglfunctions.h
)
set(OPENGL_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/qgl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglcolormap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglpixelbuffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglframebufferobject.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglextensions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglpaintdevice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglbuffer.cpp
)
include_directories(
${CMAKE_BINARY_DIR}/include
${CMAKE_BINARY_DIR}/privateinclude
${CMAKE_BINARY_DIR}/include/QtCore
${CMAKE_BINARY_DIR}/privateinclude/QtCore
${CMAKE_BINARY_DIR}/include/QtGui
${CMAKE_BINARY_DIR}/privateinclude/QtGui
${CMAKE_BINARY_DIR}/include/QtOpenGL
${CMAKE_BINARY_DIR}/privateinclude/QtOpenGL
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex
${CMAKE_CURRENT_SOURCE_DIR}/util
${CMAKE_CURRENT_BINARY_DIR}/gl2paintengineex
${CMAKE_CURRENT_BINARY_DIR}/util
${CMAKE_SOURCE_DIR}/src/core/tools
${CMAKE_SOURCE_DIR}/src/gui/painting
${CMAKE_SOURCE_DIR}/src/3rdparty/harfbuzz/src
${OPENGL_INCLUDE_DIR}
)
if(NOT WITH_OPENGLES1)
set(OPENGL_HEADERS
${OPENGL_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/qglshaderprogram.h
${CMAKE_CURRENT_SOURCE_DIR}/qglpixmapfilter_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qgraphicssystem_gl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qwindowsurface_gl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qpixmapdata_gl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglgradientcache_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglengineshadermanager_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qgl2pexvertexarray_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qpaintengineex_opengl2_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglengineshadersource_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglcustomshaderstage_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtriangulatingstroker_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtriangulator_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtextureglyphcache_gl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglshadercache_p.h
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglshadercache_meego_p.h
)
set(OPENGL_SOURCES
${OPENGL_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/qglshaderprogram.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglpixmapfilter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qgraphicssystem_gl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qwindowsurface_gl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qpixmapdata_gl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglgradientcache.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglengineshadermanager.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qgl2pexvertexarray.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qpaintengineex_opengl2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qglcustomshaderstage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtriangulatingstroker.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtriangulator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/gl2paintengineex/qtextureglyphcache_gl.cpp
)
endif()
if(NOT WITH_OPENGLES2)
set(OPENGL_HEADERS
${OPENGL_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/qpaintengine_opengl_p.h
)
set(OPENGL_SOURCES
${OPENGL_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/qpaintengine_opengl.cpp
)
endif()
if(WITH_X11 AND X11_FOUND)
if(WITH_EGL AND EGL_FOUND)
set(OPENGL_HEADERS
${OPENGL_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/qgl_egl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qpixmapdata_x11gl_p.h
${CMAKE_CURRENT_SOURCE_DIR}/qwindowsurface_x11gl_p.h
)
set(OPENGL_SOURCES
${OPENGL_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/qgl_x11egl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglpixelbuffer_egl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qgl_egl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qpixmapdata_x11gl_egl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qwindowsurface_x11gl.cpp
)
set(EXTRA_OPENGL_LIBS
${EXTRA_OPENGL_LIBS}
${EGL_LIBRARIES}
)
include_directories(${EGL_INCLUDES})
else()
set(OPENGL_SOURCES
${OPENGL_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/qgl_x11.cpp
${CMAKE_CURRENT_SOURCE_DIR}/qglpixelbuffer_x11.cpp
)
endif()
endif()
if(WITH_FREETYPE AND FREETYPE_FOUND)
set(EXTRA_OPENGL_LIBS
${EXTRA_OPENGL_LIBS}
${FREETYPE_LIBRARIES}
)
include_directories(${FREETYPE_INCLUDE_DIRS})
endif()
set(OPENGL_HEADERS
${OPENGL_HEADERS}
${CMAKE_CURRENT_SOURCE_DIR}/qopenglcommon_p.h
)
# qglfunctions.cpp must be last for all-in-one build because qglfunctions.h
# undefines from the global namespace and then defines pretty much all OpenGL
# functions into a class
set(OPENGL_SOURCES
${OPENGL_SOURCES}
${CMAKE_CURRENT_SOURCE_DIR}/qglfunctions.cpp
)
katie_generate_misc("${OPENGL_HEADERS}" QtOpenGL)
katie_generate_public("${OPENGL_PUBLIC_HEADERS}" QtOpenGL)
katie_generate_package(KtOpenGL "KtCore KtGui")
katie_setup_target(KtOpenGL ${OPENGL_SOURCES} ${OPENGL_HEADERS})
add_library(KtOpenGL ${KATIE_TYPE} ${KtOpenGL_SOURCES})
target_link_libraries(KtOpenGL ${EXTRA_OPENGL_LIBS})
set_target_properties(KtOpenGL PROPERTIES
VERSION ${KATIE_MAJOR}.${KATIE_MINOR}
SOVERSION ${KATIE_VERSION}
EXPORT_NAME OpenGL
)
install(
TARGETS KtOpenGL
EXPORT KatieLibraryTargets ${INSTALL_TARGETS_DEFAULT_ARGS}
DESTINATION ${KATIE_LIBRARIES_RELATIVE}
)
install(
DIRECTORY ${CMAKE_BINARY_DIR}/include/QtOpenGL
DESTINATION ${KATIE_HEADERS_RELATIVE}
COMPONENT Devel
)
katie_optimize_headers(${KATIE_HEADERS_FULL}/QtOpenGL)

View file

@ -1,179 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgl2pexvertexarray_p.h"
#include <qbezier_p.h>
QT_BEGIN_NAMESPACE
void QGL2PEXVertexArray::clear()
{
vertexArray.reset();
vertexArrayStops.reset();
boundingRectDirty = true;
}
QGLRect QGL2PEXVertexArray::boundingRect() const
{
if (boundingRectDirty)
return QGLRect(0.0, 0.0, 0.0, 0.0);
else
return QGLRect(minX, minY, maxX, maxY);
}
void QGL2PEXVertexArray::addClosingLine(int index)
{
QPointF point(vertexArray.at(index));
if (point != QPointF(vertexArray.last()))
vertexArray.add(point);
}
void QGL2PEXVertexArray::addCentroid(const QVectorPath &path, int subPathIndex)
{
const QPointF *const points = reinterpret_cast<const QPointF *>(path.points());
const QPainterPath::ElementType *const elements = path.elements();
QPointF sum = points[subPathIndex];
int count = 1;
for (int i = subPathIndex + 1; i < path.elementCount() && (!elements || elements[i] != QPainterPath::MoveToElement); ++i) {
sum += points[i];
++count;
}
const QPointF centroid = sum / qreal(count);
vertexArray.add(centroid);
}
void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline)
{
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
const QPainterPath::ElementType* const elements = path.elements();
if (boundingRectDirty) {
minX = maxX = points[0].x();
minY = maxY = points[0].y();
boundingRectDirty = false;
}
if (!outline && !path.isConvex())
addCentroid(path, 0);
int lastMoveTo = vertexArray.size();
vertexArray.add(points[0]); // The first element is always a moveTo
do {
if (!elements) {
// qDebug("QVectorPath has no elements");
// If the path has a null elements pointer, the elements implicitly
// start with a moveTo (already added) and continue with lineTos:
for (int i=1; i<path.elementCount(); ++i)
lineToArray(points[i].x(), points[i].y());
break;
}
// qDebug("QVectorPath has element types");
for (int i=1; i<path.elementCount(); ++i) {
switch (elements[i]) {
case QPainterPath::MoveToElement:
if (!outline)
addClosingLine(lastMoveTo);
// qDebug("element[%d] is a MoveToElement", i);
vertexArrayStops.add(vertexArray.size());
if (!outline) {
if (!path.isConvex()) addCentroid(path, i);
lastMoveTo = vertexArray.size();
}
lineToArray(points[i].x(), points[i].y()); // Add the moveTo as a new vertex
break;
case QPainterPath::LineToElement:
// qDebug("element[%d] is a LineToElement", i);
lineToArray(points[i].x(), points[i].y());
break;
case QPainterPath::CurveToElement: {
QBezier b = QBezier::fromPoints(*(((const QPointF *) points) + i - 1),
points[i],
points[i+1],
points[i+2]);
QRectF bounds = b.bounds();
// threshold based on same algorithm as in qtriangulatingstroker.cpp
int threshold = qMin<float>(64, qMax(bounds.width(), bounds.height()) * 3.14f / (curveInverseScale * 6));
if (threshold < 3) threshold = 3;
qreal one_over_threshold_minus_1 = qreal(1) / (threshold - 1);
for (int t=0; t<threshold; ++t) {
QPointF pt = b.pointAt(t * one_over_threshold_minus_1);
lineToArray(pt.x(), pt.y());
}
i += 2;
break; }
default:
break;
}
}
} while (0);
if (!outline)
addClosingLine(lastMoveTo);
vertexArrayStops.add(vertexArray.size());
}
void QGL2PEXVertexArray::lineToArray(const GLfloat x, const GLfloat y)
{
vertexArray.add(QGLPoint(x, y));
if (x > maxX)
maxX = x;
else if (x < minX)
minX = x;
if (y > maxY)
maxY = y;
else if (y < minY)
minY = y;
}
QT_END_NAMESPACE

View file

@ -1,168 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QGL2PEXVERTEXARRAY_P_H
#define QGL2PEXVERTEXARRAY_P_H
#include <qrect.h>
#include <qdatabuffer_p.h>
#include <qvectorpath_p.h>
#include <qgl_p.h>
QT_BEGIN_NAMESPACE
class QGLPoint
{
public:
QGLPoint(GLfloat new_x, GLfloat new_y) :
x(new_x), y(new_y) {};
QGLPoint(const QPointF &p) :
x(p.x()), y(p.y()) {};
QGLPoint(const QPointF* p) :
x(p->x()), y(p->y()) {};
GLfloat x;
GLfloat y;
operator QPointF() {return QPointF(x,y);}
operator QPointF() const {return QPointF(x,y);}
};
struct QGLRect
{
QGLRect(const QRectF &r)
: left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
QGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
: left(l), top(t), right(r), bottom(b) {}
GLfloat left;
GLfloat top;
GLfloat right;
GLfloat bottom;
operator QRectF() const {return QRectF(left, top, right-left, bottom-top);}
};
class QGL2PEXVertexArray
{
public:
QGL2PEXVertexArray() :
vertexArray(0), vertexArrayStops(0),
maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
boundingRectDirty(true)
{ }
inline void addRect(const QRectF &rect)
{
qreal top = rect.top();
qreal left = rect.left();
qreal bottom = rect.bottom();
qreal right = rect.right();
vertexArray << QGLPoint(left, top)
<< QGLPoint(right, top)
<< QGLPoint(right, bottom)
<< QGLPoint(right, bottom)
<< QGLPoint(left, bottom)
<< QGLPoint(left, top);
}
inline void addQuad(const QRectF &rect)
{
qreal top = rect.top();
qreal left = rect.left();
qreal bottom = rect.bottom();
qreal right = rect.right();
vertexArray << QGLPoint(left, top)
<< QGLPoint(right, top)
<< QGLPoint(left, bottom)
<< QGLPoint(right, bottom);
}
inline void addVertex(const GLfloat x, const GLfloat y)
{
vertexArray.add(QGLPoint(x, y));
}
void addPath(const QVectorPath &path, GLfloat curveInverseScale, bool outline = true);
void clear();
QGLPoint* data() {return vertexArray.data();}
int *stops() const { return vertexArrayStops.data(); }
int stopCount() const { return vertexArrayStops.size(); }
QGLRect boundingRect() const;
int vertexCount() const { return vertexArray.size(); }
void lineToArray(const GLfloat x, const GLfloat y);
private:
QDataBuffer<QGLPoint> vertexArray;
QDataBuffer<int> vertexArrayStops;
GLfloat maxX;
GLfloat maxY;
GLfloat minX;
GLfloat minY;
bool boundingRectDirty;
void addClosingLine(int index);
void addCentroid(const QVectorPath &path, int subPathIndex);
};
QT_END_NAMESPACE
#endif

View file

@ -1,142 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qglcustomshaderstage_p.h"
#include "qglengineshadermanager_p.h"
#include "qpaintengineex_opengl2_p.h"
#include <qpainter_p.h>
QT_BEGIN_NAMESPACE
class QGLCustomShaderStagePrivate
{
public:
QGLCustomShaderStagePrivate() :
m_manager(0) {}
QPointer<QGLEngineShaderManager> m_manager;
QByteArray m_source;
};
QGLCustomShaderStage::QGLCustomShaderStage()
: d_ptr(new QGLCustomShaderStagePrivate)
{
}
QGLCustomShaderStage::~QGLCustomShaderStage()
{
Q_D(QGLCustomShaderStage);
if (d->m_manager) {
d->m_manager->removeCustomStage();
d->m_manager->sharedShaders->cleanupCustomStage(this);
}
}
void QGLCustomShaderStage::setUniformsDirty()
{
Q_D(QGLCustomShaderStage);
if (d->m_manager)
d->m_manager->setDirty(); // ### Probably a bit overkill!
}
bool QGLCustomShaderStage::setOnPainter(QPainter* p)
{
Q_D(QGLCustomShaderStage);
if (p->paintEngine()->type() != QPaintEngine::OpenGL2) {
qWarning("QGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2");
return false;
}
if (d->m_manager)
qWarning("Custom shader is already set on a painter");
QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx*>(p->paintEngine());
d->m_manager = QGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
Q_ASSERT(d->m_manager);
d->m_manager->setCustomStage(this);
return true;
}
void QGLCustomShaderStage::removeFromPainter(QPainter* p)
{
Q_D(QGLCustomShaderStage);
if (p->paintEngine()->type() != QPaintEngine::OpenGL2)
return;
QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx*>(p->paintEngine());
d->m_manager = QGL2PaintEngineExPrivate::shaderManagerForEngine(engine);
Q_ASSERT(d->m_manager);
// Just set the stage to null, don't call removeCustomStage().
// This should leave the program in a compiled/linked state
// if the next custom shader stage is this one again.
d->m_manager->setCustomStage(0);
d->m_manager = 0;
}
QByteArray QGLCustomShaderStage::source() const
{
Q_D(const QGLCustomShaderStage);
return d->m_source;
}
// Called by the shader manager if another custom shader is attached or
// the manager is deleted
void QGLCustomShaderStage::setInactive()
{
Q_D(QGLCustomShaderStage);
d->m_manager = 0;
}
void QGLCustomShaderStage::setSource(const QByteArray& s)
{
Q_D(QGLCustomShaderStage);
d->m_source = s;
}
QT_END_NAMESPACE

View file

@ -1,92 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGL_CUSTOM_SHADER_STAGE_H
#define QGL_CUSTOM_SHADER_STAGE_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QGLShaderProgram>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGLCustomShaderStagePrivate;
class Q_OPENGL_EXPORT QGLCustomShaderStage
{
Q_DECLARE_PRIVATE(QGLCustomShaderStage)
public:
QGLCustomShaderStage();
virtual ~QGLCustomShaderStage();
virtual void setUniforms(QGLShaderProgram*) {}
void setUniformsDirty();
bool setOnPainter(QPainter*);
void removeFromPainter(QPainter*);
QByteArray source() const;
void setInactive();
protected:
void setSource(const QByteArray&);
private:
QGLCustomShaderStagePrivate* d_ptr;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View file

@ -1,844 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qglengineshadermanager_p.h"
#include "qglengineshadersource_p.h"
#include "qpaintengineex_opengl2_p.h"
#include "qglshadercache_p.h"
#if defined(QT_DEBUG)
#include <QMetaObject>
#endif
// #define QT_GL_SHARED_SHADER_DEBUG
QT_BEGIN_NAMESPACE
class QGLShaderStorage
{
public:
QGLEngineSharedShaders *shadersForThread(const QGLContext *context) {
QGLContextGroupResource<QGLEngineSharedShaders> *&shaders = m_storage.localData();
if (!shaders)
shaders = new QGLContextGroupResource<QGLEngineSharedShaders>();
return shaders->value(context);
}
private:
QThreadStorage<QGLContextGroupResource<QGLEngineSharedShaders> *> m_storage;
};
Q_GLOBAL_STATIC(QGLShaderStorage, qt_shader_storage)
QGLEngineSharedShaders *QGLEngineSharedShaders::shadersForContext(const QGLContext *context)
{
return qt_shader_storage()->shadersForThread(context);
}
const char* QGLEngineSharedShaders::qShaderSnippets[] = {
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0
};
QGLEngineSharedShaders::QGLEngineSharedShaders(const QGLContext* context)
: ctxGuard(context)
, blitShaderProg(0)
, simpleShaderProg(0)
{
/*
Rather than having the shader source array statically initialised, it is initialised
here instead. This is to allow new shader names to be inserted or existing names moved
around without having to change the order of the glsl strings. It is hoped this will
make future hard-to-find runtime bugs more obvious and generally give more solid code.
*/
static bool snippetsPopulated = false;
if (!snippetsPopulated) {
const char** code = qShaderSnippets; // shortcut
code[MainVertexShader] = qglslMainVertexShader;
code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
code[MainWithTexCoordsAndOpacityVertexShader] = qglslMainWithTexCoordsAndOpacityVertexShader;
code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
code[ComplexGeometryPositionOnlyVertexShader] = qglslComplexGeometryPositionOnlyVertexShader;
code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader;
code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader;
code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader;
code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader;
code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader;
code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader;
code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader;
code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader;
code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO;
code[MainFragmentShader_CM] = qglslMainFragmentShader_CM;
code[MainFragmentShader_MO] = qglslMainFragmentShader_MO;
code[MainFragmentShader_M] = qglslMainFragmentShader_M;
code[MainFragmentShader_CO] = qglslMainFragmentShader_CO;
code[MainFragmentShader_C] = qglslMainFragmentShader_C;
code[MainFragmentShader_O] = qglslMainFragmentShader_O;
code[MainFragmentShader] = qglslMainFragmentShader;
code[MainFragmentShader_ImageArrays] = qglslMainFragmentShader_ImageArrays;
code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
code[CustomImageSrcFragmentShader] = qglslCustomSrcFragmentShader; // Calls "customShader", which must be appended
code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
code[NoMaskFragmentShader] = "";
code[MaskFragmentShader] = qglslMaskFragmentShader;
code[RgbMaskFragmentShaderPass1] = qglslRgbMaskFragmentShaderPass1;
code[RgbMaskFragmentShaderPass2] = qglslRgbMaskFragmentShaderPass2;
code[RgbMaskWithGammaFragmentShader] = ""; //###
code[NoCompositionModeFragmentShader] = "";
code[MultiplyCompositionModeFragmentShader] = ""; //###
code[ScreenCompositionModeFragmentShader] = ""; //###
code[OverlayCompositionModeFragmentShader] = ""; //###
code[DarkenCompositionModeFragmentShader] = ""; //###
code[LightenCompositionModeFragmentShader] = ""; //###
code[ColorDodgeCompositionModeFragmentShader] = ""; //###
code[ColorBurnCompositionModeFragmentShader] = ""; //###
code[HardLightCompositionModeFragmentShader] = ""; //###
code[SoftLightCompositionModeFragmentShader] = ""; //###
code[DifferenceCompositionModeFragmentShader] = ""; //###
code[ExclusionCompositionModeFragmentShader] = ""; //###
#if defined(QT_DEBUG)
// Check that all the elements have been filled:
for (int i = 0; i < TotalSnippetCount; ++i) {
if (qShaderSnippets[i] == 0) {
qFatal("Shader snippet for %s (#%d) is missing!",
snippetNameStr(SnippetName(i)).constData(), i);
}
}
#endif
snippetsPopulated = true;
}
QGLShader* fragShader;
QGLShader* vertexShader;
QByteArray vertexSource;
QByteArray fragSource;
// Compile up the simple shader:
vertexSource.append(qShaderSnippets[MainVertexShader]);
vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
fragSource.append(qShaderSnippets[MainFragmentShader]);
fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
simpleShaderProg = new QGLShaderProgram(context, 0);
CachedShader simpleShaderCache(fragSource, vertexSource);
bool inCache = simpleShaderCache.load(simpleShaderProg, context);
if (!inCache) {
vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
shaders.append(vertexShader);
if (!vertexShader->compileSourceCode(vertexSource))
qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
fragShader = new QGLShader(QGLShader::Fragment, context, 0);
shaders.append(fragShader);
if (!fragShader->compileSourceCode(fragSource))
qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
simpleShaderProg->addShader(vertexShader);
simpleShaderProg->addShader(fragShader);
simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
}
simpleShaderProg->link();
if (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 QGLShaderProgram(context, 0);
CachedShader blitShaderCache(fragSource, vertexSource);
inCache = blitShaderCache.load(blitShaderProg, context);
if (!inCache) {
vertexShader = new QGLShader(QGLShader::Vertex, context, 0);
shaders.append(vertexShader);
if (!vertexShader->compileSourceCode(vertexSource))
qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
fragShader = new QGLShader(QGLShader::Fragment, context, 0);
shaders.append(fragShader);
if (!fragShader->compileSourceCode(fragSource))
qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
blitShaderProg->addShader(vertexShader);
blitShaderProg->addShader(fragShader);
blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
}
blitShaderProg->link();
if (blitShaderProg->isLinked()) {
if (!inCache)
blitShaderCache.store(blitShaderProg, context);
} else {
qCritical() << "Errors linking blit shader:"
<< blitShaderProg->log();
}
#ifdef QT_GL_SHARED_SHADER_DEBUG
qDebug(" -> QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
#endif
}
QGLEngineSharedShaders::~QGLEngineSharedShaders()
{
#ifdef QT_GL_SHARED_SHADER_DEBUG
qDebug(" -> ~QGLEngineSharedShaders() %p for thread %p.", this, QThread::currentThread());
#endif
qDeleteAll(shaders);
shaders.clear();
qDeleteAll(cachedPrograms);
cachedPrograms.clear();
if (blitShaderProg) {
delete blitShaderProg;
blitShaderProg = 0;
}
if (simpleShaderProg) {
delete simpleShaderProg;
simpleShaderProg = 0;
}
}
#if defined (QT_DEBUG)
QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name)
{
QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("SnippetName"));
return QByteArray(m.valueToKey(name));
}
#endif
// The address returned here will only be valid until next time this function is called.
// The program is return bound.
QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog)
{
for (int i = 0; i < cachedPrograms.size(); ++i) {
QGLEngineShaderProg *cachedProg = cachedPrograms[i];
if (*cachedProg == prog) {
// Move the program to the top of the list as a poor-man's cache algo
cachedPrograms.move(i, 0);
cachedProg->program->bind();
return cachedProg;
}
}
QScopedPointer<QGLEngineShaderProg> newProg;
do {
QByteArray fragSource;
// Insert the custom stage before the srcPixel shader to work around an ATI driver bug
// where you cannot forward declare a function that takes a sampler as argument.
if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
fragSource.append(prog.customStageSource);
fragSource.append(qShaderSnippets[prog.mainFragShader]);
fragSource.append(qShaderSnippets[prog.srcPixelFragShader]);
if (prog.compositionFragShader)
fragSource.append(qShaderSnippets[prog.compositionFragShader]);
if (prog.maskFragShader)
fragSource.append(qShaderSnippets[prog.maskFragShader]);
QByteArray vertexSource;
vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram(ctxGuard.context(), 0));
CachedShader shaderCache(fragSource, vertexSource);
bool inCache = shaderCache.load(shaderProgram.data(), ctxGuard.context());
if (!inCache) {
QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment, ctxGuard.context(), 0));
QByteArray description;
#if defined(QT_DEBUG)
// Name the shader for easier debugging
description.append("Fragment shader: main=");
description.append(snippetNameStr(prog.mainFragShader));
description.append(", srcPixel=");
description.append(snippetNameStr(prog.srcPixelFragShader));
if (prog.compositionFragShader) {
description.append(", composition=");
description.append(snippetNameStr(prog.compositionFragShader));
}
if (prog.maskFragShader) {
description.append(", mask=");
description.append(snippetNameStr(prog.maskFragShader));
}
fragShader->setObjectName(QString::fromLatin1(description));
#endif
if (!fragShader->compileSourceCode(fragSource)) {
qWarning() << "Warning:" << description << "failed to compile!";
break;
}
QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex, ctxGuard.context(), 0));
#if defined(QT_DEBUG)
// Name the shader for easier debugging
description.clear();
description.append("Vertex shader: main=");
description.append(snippetNameStr(prog.mainVertexShader));
description.append(", position=");
description.append(snippetNameStr(prog.positionVertexShader));
vertexShader->setObjectName(QString::fromLatin1(description));
#endif
if (!vertexShader->compileSourceCode(vertexSource)) {
qWarning() << "Warning:" << description << "failed to compile!";
break;
}
shaders.append(vertexShader.data());
shaders.append(fragShader.data());
shaderProgram->addShader(vertexShader.take());
shaderProgram->addShader(fragShader.take());
// We have to bind the vertex attribute names before the program is linked:
shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
if (prog.useTextureCoords)
shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
if (prog.useOpacityAttribute)
shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
if (prog.usePmvMatrixAttribute) {
shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
}
}
newProg.reset(new QGLEngineShaderProg(prog));
newProg->program = shaderProgram.take();
newProg->program->link();
if (newProg->program->isLinked()) {
if (!inCache)
shaderCache.store(newProg->program, ctxGuard.context());
} 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) {
QGLShader *shader = newProg->program->shaders().at(i);
error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n")
+ QLatin1String(shader->sourceCode()) + br;
}
#endif
error += QLatin1String(" Error Log:\n")
+ QLatin1String(" ") + newProg->program->log();
qWarning() << error;
break;
}
newProg->program->bind();
if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) {
GLuint location = newProg->program->uniformLocation("maskTexture");
newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT);
}
if (cachedPrograms.count() > 30) {
// The cache is full, so delete the last 5 programs in the list.
// These programs will be least used, as a program us bumped to
// the top of the list when it's used.
for (int i = 0; i < 5; ++i) {
delete cachedPrograms.last();
cachedPrograms.removeLast();
}
}
cachedPrograms.insert(0, newProg.data());
} while (false);
return newProg.take();
}
void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage)
{
// Remove any shader programs which has this as the custom shader src:
for (int i = 0; i < cachedPrograms.size(); ++i) {
QGLEngineShaderProg *cachedProg = cachedPrograms[i];
if (cachedProg->customStageSource == stage->source()) {
delete cachedProg;
cachedPrograms.removeAt(i);
i--;
}
}
}
QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
: ctx(context),
shaderProgNeedsChanging(true),
complexGeometry(false),
srcPixelType(Qt::NoBrush),
opacityMode(NoOpacity),
maskType(NoMask),
compositionMode(QPainter::CompositionMode_SourceOver),
customSrcStage(0),
currentShaderProg(0)
{
sharedShaders = QGLEngineSharedShaders::shadersForContext(context);
}
QGLEngineShaderManager::~QGLEngineShaderManager()
{
//###
removeCustomStage();
}
GLuint QGLEngineShaderManager::getUniformLocation(Uniform id)
{
if (!currentShaderProg)
return 0;
QVector<uint> &uniformLocations = currentShaderProg->uniformLocations;
if (uniformLocations.isEmpty())
uniformLocations.fill(GLuint(-1), NumUniforms);
static const char *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 QGLEngineShaderManager::optimiseForBrushTransform(QTransform::TransformationType transformType)
{
Q_UNUSED(transformType); // Currently ignored
}
void QGLEngineShaderManager::setDirty()
{
shaderProgNeedsChanging = true;
}
void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
{
Q_ASSERT(style != Qt::NoBrush);
if (srcPixelType == PixelSrcType(style))
return;
srcPixelType = style;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
{
if (srcPixelType == type)
return;
srcPixelType = type;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setOpacityMode(OpacityMode mode)
{
if (opacityMode == mode)
return;
opacityMode = mode;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setMaskType(MaskType type)
{
if (maskType == type)
return;
maskType = type;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
{
if (compositionMode == mode)
return;
compositionMode = mode;
shaderProgNeedsChanging = true; //###
}
void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage)
{
if (customSrcStage)
removeCustomStage();
customSrcStage = stage;
shaderProgNeedsChanging = true;
}
void QGLEngineShaderManager::removeCustomStage()
{
if (customSrcStage)
customSrcStage->setInactive();
customSrcStage = 0;
shaderProgNeedsChanging = true;
}
QGLShaderProgram* QGLEngineShaderManager::currentProgram()
{
if (currentShaderProg)
return currentShaderProg->program;
else
return sharedShaders->simpleProgram();
}
void QGLEngineShaderManager::useSimpleProgram()
{
sharedShaders->simpleProgram()->bind();
QGLContextPrivate* ctx_d = ctx->d_func();
ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, false);
ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
shaderProgNeedsChanging = true;
}
void QGLEngineShaderManager::useBlitProgram()
{
sharedShaders->blitProgram()->bind();
QGLContextPrivate* ctx_d = ctx->d_func();
ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, true);
ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, false);
shaderProgNeedsChanging = true;
}
QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
{
return sharedShaders->simpleProgram();
}
QGLShaderProgram* QGLEngineShaderManager::blitProgram()
{
return sharedShaders->blitProgram();
}
// Select & use the correct shader program using the current state.
// Returns true if program needed changing.
bool QGLEngineShaderManager::useCorrectShaderProg()
{
if (!shaderProgNeedsChanging)
return false;
bool useCustomSrc = customSrcStage != 0;
if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc && srcPixelType != Qt::TexturePattern) {
useCustomSrc = false;
qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src");
}
QGLEngineShaderProg requiredProgram;
bool texCoords = false;
// Choose vertex shader shader position function (which typically also sets
// varyings) and the source pixel (srcPixel) fragment shader function:
requiredProgram.positionVertexShader = QGLEngineSharedShaders::InvalidSnippetName;
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::InvalidSnippetName;
bool isAffine = brushTransform.isAffine();
if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
if (isAffine)
requiredProgram.positionVertexShader = QGLEngineSharedShaders::AffinePositionWithPatternBrushVertexShader;
else
requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionWithPatternBrushVertexShader;
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::PatternBrushSrcFragmentShader;
}
else switch (srcPixelType) {
default:
case Qt::NoBrush:
qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set");
break;
case QGLEngineShaderManager::ImageSrc:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcFragmentShader;
requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
texCoords = true;
break;
case QGLEngineShaderManager::NonPremultipliedImageSrc:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::NonPremultipliedImageSrcFragmentShader;
requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
texCoords = true;
break;
case QGLEngineShaderManager::PatternSrc:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ImageSrcWithPatternFragmentShader;
requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
texCoords = true;
break;
case QGLEngineShaderManager::TextureSrcWithPattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcWithPatternFragmentShader;
requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
: QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
break;
case Qt::SolidPattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::SolidBrushSrcFragmentShader;
requiredProgram.positionVertexShader = QGLEngineSharedShaders::PositionOnlyVertexShader;
break;
case Qt::LinearGradientPattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::LinearGradientBrushSrcFragmentShader;
requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithLinearGradientBrushVertexShader
: QGLEngineSharedShaders::PositionWithLinearGradientBrushVertexShader;
break;
case Qt::ConicalGradientPattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::ConicalGradientBrushSrcFragmentShader;
requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithConicalGradientBrushVertexShader
: QGLEngineSharedShaders::PositionWithConicalGradientBrushVertexShader;
break;
case Qt::RadialGradientPattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::RadialGradientBrushSrcFragmentShader;
requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithRadialGradientBrushVertexShader
: QGLEngineSharedShaders::PositionWithRadialGradientBrushVertexShader;
break;
case Qt::TexturePattern:
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::TextureBrushSrcFragmentShader;
requiredProgram.positionVertexShader = isAffine ? QGLEngineSharedShaders::AffinePositionWithTextureBrushVertexShader
: QGLEngineSharedShaders::PositionWithTextureBrushVertexShader;
break;
};
if (useCustomSrc) {
requiredProgram.srcPixelFragShader = QGLEngineSharedShaders::CustomImageSrcFragmentShader;
requiredProgram.customStageSource = customSrcStage->source();
}
const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
// Choose fragment shader main function:
if (opacityMode == AttributeOpacity) {
Q_ASSERT(!hasCompose && !hasMask);
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_ImageArrays;
} else {
bool useGlobalOpacity = (opacityMode == UniformOpacity);
if (hasCompose && hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CMO;
if (hasCompose && hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CM;
if (!hasCompose && hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_MO;
if (!hasCompose && hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_M;
if (hasCompose && !hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_CO;
if (hasCompose && !hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_C;
if (!hasCompose && !hasMask && useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader_O;
if (!hasCompose && !hasMask && !useGlobalOpacity)
requiredProgram.mainFragShader = QGLEngineSharedShaders::MainFragmentShader;
}
if (hasMask) {
if (maskType == PixelMask) {
requiredProgram.maskFragShader = QGLEngineSharedShaders::MaskFragmentShader;
texCoords = true;
} else if (maskType == SubPixelMaskPass1) {
requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass1;
texCoords = true;
} else if (maskType == SubPixelMaskPass2) {
requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskFragmentShaderPass2;
texCoords = true;
} else if (maskType == SubPixelWithGammaMask) {
requiredProgram.maskFragShader = QGLEngineSharedShaders::RgbMaskWithGammaFragmentShader;
texCoords = true;
} else {
qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
}
} else {
requiredProgram.maskFragShader = QGLEngineSharedShaders::NoMaskFragmentShader;
}
if (hasCompose) {
switch (compositionMode) {
case QPainter::CompositionMode_Multiply:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::MultiplyCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Screen:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::ScreenCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Overlay:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::OverlayCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Darken:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::DarkenCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Lighten:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::LightenCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_ColorDodge:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorDodgeCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_ColorBurn:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::ColorBurnCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_HardLight:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::HardLightCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_SoftLight:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::SoftLightCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Difference:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::DifferenceCompositionModeFragmentShader;
break;
case QPainter::CompositionMode_Exclusion:
requiredProgram.compositionFragShader = QGLEngineSharedShaders::ExclusionCompositionModeFragmentShader;
break;
default:
qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
}
} else {
requiredProgram.compositionFragShader = QGLEngineSharedShaders::NoCompositionModeFragmentShader;
}
// Choose vertex shader main function
if (opacityMode == AttributeOpacity) {
Q_ASSERT(texCoords);
requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsAndOpacityVertexShader;
} else if (texCoords) {
requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainWithTexCoordsVertexShader;
} else {
requiredProgram.mainVertexShader = QGLEngineSharedShaders::MainVertexShader;
}
requiredProgram.useTextureCoords = texCoords;
requiredProgram.useOpacityAttribute = (opacityMode == AttributeOpacity);
if (complexGeometry && srcPixelType == Qt::SolidPattern) {
requiredProgram.positionVertexShader = QGLEngineSharedShaders::ComplexGeometryPositionOnlyVertexShader;
requiredProgram.usePmvMatrixAttribute = false;
} else {
requiredProgram.usePmvMatrixAttribute = true;
// Force complexGeometry off, since we currently don't support that mode for
// non-solid brushes
complexGeometry = false;
}
// At this point, requiredProgram is fully populated so try to find the program in the cache
currentShaderProg = sharedShaders->findProgramInCache(requiredProgram);
if (currentShaderProg && useCustomSrc) {
customSrcStage->setUniforms(currentShaderProg->program);
}
// Make sure all the vertex attribute arrays the program uses are enabled (and the ones it
// doesn't use are disabled)
QGLContextPrivate* ctx_d = ctx->d_func();
ctx_d->setVertexAttribArrayEnabled(QT_VERTEX_COORDS_ATTR, true);
ctx_d->setVertexAttribArrayEnabled(QT_TEXTURE_COORDS_ATTR, currentShaderProg && currentShaderProg->useTextureCoords);
ctx_d->setVertexAttribArrayEnabled(QT_OPACITY_ATTR, currentShaderProg && currentShaderProg->useOpacityAttribute);
shaderProgNeedsChanging = false;
return true;
}
QT_END_NAMESPACE
#include "moc_qglengineshadermanager_p.h"

View file

@ -1,513 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
/*
VERTEX SHADERS
==============
Vertex shaders are specified as multiple (partial) shaders. On desktop,
this works fine. On ES, QGLShader & QGLShaderProgram will make partial
shaders work by concatenating the source in each QGLShader and compiling
it as a single shader. This is abstracted nicely by QGLShaderProgram and
the GL2 engine doesn't need to worry about it.
Generally, there's two vertex shader objects. The position shaders are
the ones which set gl_Position. There's also two "main" vertex shaders,
one which just calls the position shader and another which also passes
through some texture coordinates from a vertex attribute array to a
varying. These texture coordinates are used for mask position in text
rendering and for the source coordinates in drawImage/drawPixmap. There's
also a "Simple" vertex shader for rendering a solid colour (used to render
into the stencil buffer where the actual colour value is discarded).
The position shaders for brushes look scary. This is because many of the
calculations which logically belong in the fragment shader have been moved
into the vertex shader to improve performance. This is why the position
calculation is in a separate shader. Not only does it calculate the
position, but it also calculates some data to be passed to the fragment
shader as a varying. It is optimal to move as much of the calculation as
possible into the vertex shader as this is executed less often.
The varyings passed to the fragment shaders are interpolated (which is
cheap). Unfortunately, GL will apply perspective correction to the
interpolation calusing errors. To get around this, the vertex shader must
apply perspective correction itself and set the w-value of gl_Position to
zero. That way, GL will be tricked into thinking it doesn't need to apply a
perspective correction and use linear interpolation instead (which is what
we want). Of course, if the brush transform is affeine, no perspective
correction is needed and a simpler vertex shader can be used instead.
So there are the following "main" vertex shaders:
qglslMainVertexShader
qglslMainWithTexCoordsVertexShader
And the the following position vertex shaders:
qglslPositionOnlyVertexShader
qglslPositionWithTextureBrushVertexShader
qglslPositionWithPatternBrushVertexShader
qglslPositionWithLinearGradientBrushVertexShader
qglslPositionWithRadialGradientBrushVertexShader
qglslPositionWithConicalGradientBrushVertexShader
qglslAffinePositionWithTextureBrushVertexShader
qglslAffinePositionWithPatternBrushVertexShader
qglslAffinePositionWithLinearGradientBrushVertexShader
qglslAffinePositionWithRadialGradientBrushVertexShader
qglslAffinePositionWithConicalGradientBrushVertexShader
Leading to 23 possible vertex shaders
FRAGMENT SHADERS
================
Fragment shaders are also specified as multiple (partial) shaders. The
different fragment shaders represent the different stages in Qt's fragment
pipeline. There are 1-3 stages in this pipeline: First stage is to get the
fragment's colour value. The next stage is to get the fragment's mask value
(coverage value for anti-aliasing) and the final stage is to blend the
incoming fragment with the background (for composition modes not supported
by GL).
Of these, the first stage will always be present. If Qt doesn't need to
apply anti-aliasing (because it's off or handled by multisampling) then
the coverage value doesn't need to be applied. (Note: There are two types
of mask, one for regular anti-aliasing and one for sub-pixel anti-
aliasing.) If the composition mode is one which GL supports natively then
the blending stage doesn't need to be applied.
As eash stage can have multiple implementations, they are abstracted as
GLSL function calls with the following signatures:
Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()":
qglslImageSrcFragShader
qglslImageSrcWithPatternFragShader
qglslNonPremultipliedImageSrcFragShader
qglslSolidBrushSrcFragShader
qglslTextureBrushSrcFragShader
qglslTextureBrushWithPatternFragShader
qglslPatternBrushSrcFragShader
qglslLinearGradientBrushSrcFragShader
qglslRadialGradientBrushSrcFragShader
qglslConicalGradientBrushSrcFragShader
NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
qglslMaskFragmentShader
qglslRgbMaskFragmentShaderPass1
qglslRgbMaskFragmentShaderPass2
qglslRgbMaskWithGammaFragmentShader
Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
qglslColorBurnCompositionModeFragmentShader
qglslColorDodgeCompositionModeFragmentShader
qglslDarkenCompositionModeFragmentShader
qglslDifferenceCompositionModeFragmentShader
qglslExclusionCompositionModeFragmentShader
qglslHardLightCompositionModeFragmentShader
qglslLightenCompositionModeFragmentShader
qglslMultiplyCompositionModeFragmentShader
qglslOverlayCompositionModeFragmentShader
qglslScreenCompositionModeFragmentShader
qglslSoftLightCompositionModeFragmentShader
Note: In the future, some GLSL compilers will support an extension allowing
a new 'color' precision specifier. To support this, qcolorp is used for
all color components so it can be defined to colorp or lowp depending upon
the implementation.
So there are differnt frament shader main functions, depending on the
number & type of pipelines the fragment needs to go through.
The choice of which main() fragment shader string to use depends on:
- Use of global opacity
- Brush style (some brushes apply opacity themselves)
- Use & type of mask (TODO: Need to support high quality anti-aliasing & text)
- Use of non-GL Composition mode
Leading to the following fragment shader main functions:
gl_FragColor = compose(applyMask(srcPixel()*globalOpacity));
gl_FragColor = compose(applyMask(srcPixel()));
gl_FragColor = applyMask(srcPixel()*globalOpacity);
gl_FragColor = applyMask(srcPixel());
gl_FragColor = compose(srcPixel()*globalOpacity);
gl_FragColor = compose(srcPixel());
gl_FragColor = srcPixel()*globalOpacity;
gl_FragColor = srcPixel();
Called:
qglslMainFragmentShader_CMO
qglslMainFragmentShader_CM
qglslMainFragmentShader_MO
qglslMainFragmentShader_M
qglslMainFragmentShader_CO
qglslMainFragmentShader_C
qglslMainFragmentShader_O
qglslMainFragmentShader
Where:
M = Mask
C = Composition
O = Global Opacity
CUSTOM SHADER CODE
==================
The use of custom shader code is supported by the engine for drawImage and
drawPixmap calls. This is implemented via hooks in the fragment pipeline.
The custom shader is passed to the engine as a partial fragment shader
(QGLCustomShaderStage). The shader will implement a pre-defined method name
which Qt's fragment pipeline will call:
lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords)
The provided src and srcCoords parameters can be used to sample from the
source image.
Transformations, clipping, opacity, and composition modes set using QPainter
will be respected when using the custom shader hook.
*/
#ifndef QGLENGINE_SHADER_MANAGER_H
#define QGLENGINE_SHADER_MANAGER_H
#include <QGLShaderProgram>
#include <QPainter>
#include <qgl_p.h>
#include <qglcustomshaderstage_p.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
/*
struct QGLEngineCachedShaderProg
{
QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
QGLEngineShaderManager::ShaderName vertexPosition,
QGLEngineShaderManager::ShaderName fragMain,
QGLEngineShaderManager::ShaderName pixelSrc,
QGLEngineShaderManager::ShaderName mask,
QGLEngineShaderManager::ShaderName composition);
int cacheKey;
QGLShaderProgram* program;
}
*/
static const GLuint QT_VERTEX_COORDS_ATTR = 0;
static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
static const GLuint QT_OPACITY_ATTR = 2;
static const GLuint QT_PMV_MATRIX_1_ATTR = 3;
static const GLuint QT_PMV_MATRIX_2_ATTR = 4;
static const GLuint QT_PMV_MATRIX_3_ATTR = 5;
class QGLEngineShaderProg;
class Q_OPENGL_EXPORT QGLEngineSharedShaders
{
Q_GADGET
public:
enum SnippetName {
MainVertexShader,
MainWithTexCoordsVertexShader,
MainWithTexCoordsAndOpacityVertexShader,
// UntransformedPositionVertexShader must be first in the list:
UntransformedPositionVertexShader,
PositionOnlyVertexShader,
ComplexGeometryPositionOnlyVertexShader,
PositionWithPatternBrushVertexShader,
PositionWithLinearGradientBrushVertexShader,
PositionWithConicalGradientBrushVertexShader,
PositionWithRadialGradientBrushVertexShader,
PositionWithTextureBrushVertexShader,
AffinePositionWithPatternBrushVertexShader,
AffinePositionWithLinearGradientBrushVertexShader,
AffinePositionWithConicalGradientBrushVertexShader,
AffinePositionWithRadialGradientBrushVertexShader,
AffinePositionWithTextureBrushVertexShader,
// MainFragmentShader_CMO must be first in the list:
MainFragmentShader_CMO,
MainFragmentShader_CM,
MainFragmentShader_MO,
MainFragmentShader_M,
MainFragmentShader_CO,
MainFragmentShader_C,
MainFragmentShader_O,
MainFragmentShader,
MainFragmentShader_ImageArrays,
// ImageSrcFragmentShader must be first in the list::
ImageSrcFragmentShader,
ImageSrcWithPatternFragmentShader,
NonPremultipliedImageSrcFragmentShader,
CustomImageSrcFragmentShader,
SolidBrushSrcFragmentShader,
TextureBrushSrcFragmentShader,
TextureBrushSrcWithPatternFragmentShader,
PatternBrushSrcFragmentShader,
LinearGradientBrushSrcFragmentShader,
RadialGradientBrushSrcFragmentShader,
ConicalGradientBrushSrcFragmentShader,
ShockingPinkSrcFragmentShader,
// NoMaskFragmentShader must be first in the list:
NoMaskFragmentShader,
MaskFragmentShader,
RgbMaskFragmentShaderPass1,
RgbMaskFragmentShaderPass2,
RgbMaskWithGammaFragmentShader,
// NoCompositionModeFragmentShader must be first in the list:
NoCompositionModeFragmentShader,
MultiplyCompositionModeFragmentShader,
ScreenCompositionModeFragmentShader,
OverlayCompositionModeFragmentShader,
DarkenCompositionModeFragmentShader,
LightenCompositionModeFragmentShader,
ColorDodgeCompositionModeFragmentShader,
ColorBurnCompositionModeFragmentShader,
HardLightCompositionModeFragmentShader,
SoftLightCompositionModeFragmentShader,
DifferenceCompositionModeFragmentShader,
ExclusionCompositionModeFragmentShader,
TotalSnippetCount, InvalidSnippetName
};
#if defined (QT_DEBUG)
Q_ENUMS(SnippetName)
static QByteArray snippetNameStr(SnippetName snippetName);
#endif
/*
// These allow the ShaderName enum to be used as a cache key
const int mainVertexOffset = 0;
const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
const int maskOffset = (1<<14) - NoMaskShader;
const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
*/
QGLEngineSharedShaders(const QGLContext *context);
~QGLEngineSharedShaders();
QGLShaderProgram *simpleProgram() { return simpleShaderProg; }
QGLShaderProgram *blitProgram() { return blitShaderProg; }
// Compile the program if it's not already in the cache, return the item in the cache.
QGLEngineShaderProg *findProgramInCache(const QGLEngineShaderProg &prog);
// Compile the custom shader if it's not already in the cache, return the item in the cache.
static QGLEngineSharedShaders *shadersForContext(const QGLContext *context);
// Ideally, this would be static and cleanup all programs in all contexts which
// contain the custom code. Currently it is just a hint and we rely on deleted
// custom shaders being cleaned up by being kicked out of the cache when it's
// full.
void cleanupCustomStage(QGLCustomShaderStage* stage);
private:
QGLSharedResourceGuard ctxGuard;
QGLShaderProgram *blitShaderProg;
QGLShaderProgram *simpleShaderProg;
QList<QGLEngineShaderProg*> cachedPrograms;
QList<QGLShader *> shaders;
static const char* qShaderSnippets[TotalSnippetCount];
};
class QGLEngineShaderProg
{
public:
QGLEngineShaderProg() : program(0) {}
~QGLEngineShaderProg() {
if (program)
delete program;
}
QGLEngineSharedShaders::SnippetName mainVertexShader;
QGLEngineSharedShaders::SnippetName positionVertexShader;
QGLEngineSharedShaders::SnippetName mainFragShader;
QGLEngineSharedShaders::SnippetName srcPixelFragShader;
QGLEngineSharedShaders::SnippetName maskFragShader;
QGLEngineSharedShaders::SnippetName compositionFragShader;
QByteArray customStageSource; //TODO: Decent cache key for custom stages
QGLShaderProgram* program;
QVector<uint> uniformLocations;
bool useTextureCoords;
bool useOpacityAttribute;
bool usePmvMatrixAttribute;
bool operator==(const QGLEngineShaderProg& other) {
// We don't care about the program
return ( mainVertexShader == other.mainVertexShader &&
positionVertexShader == other.positionVertexShader &&
mainFragShader == other.mainFragShader &&
srcPixelFragShader == other.srcPixelFragShader &&
maskFragShader == other.maskFragShader &&
compositionFragShader == other.compositionFragShader &&
customStageSource == other.customStageSource
);
}
};
class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject
{
Q_OBJECT
public:
QGLEngineShaderManager(QGLContext* context);
~QGLEngineShaderManager();
enum MaskType {NoMask, PixelMask, SubPixelMaskPass1, SubPixelMaskPass2, SubPixelWithGammaMask};
enum PixelSrcType {
ImageSrc = Qt::TexturePattern+1,
NonPremultipliedImageSrc = Qt::TexturePattern+2,
PatternSrc = Qt::TexturePattern+3,
TextureSrcWithPattern = Qt::TexturePattern+4
};
enum Uniform {
ImageTexture,
PatternColor,
GlobalOpacity,
Depth,
MaskTexture,
FragmentColor,
LinearData,
Angle,
HalfViewportSize,
Fmp,
Fmp2MRadius2,
Inverse2Fmp2MRadius2,
SqrFr,
BRadius,
InvertedTextureSize,
BrushTransform,
BrushTexture,
Matrix,
NumUniforms
};
enum OpacityMode {
NoOpacity,
UniformOpacity,
AttributeOpacity
};
// There are optimizations we can do, depending on the brush transform:
// 1) May not have to apply perspective-correction
// 2) Can use lower precision for matrix
void optimiseForBrushTransform(QTransform::TransformationType transformType);
void setSrcPixelType(Qt::BrushStyle);
void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
void setOpacityMode(OpacityMode);
void setMaskType(MaskType);
void setCompositionMode(QPainter::CompositionMode);
void setCustomStage(QGLCustomShaderStage* stage);
void removeCustomStage();
GLuint getUniformLocation(Uniform id);
void setDirty(); // someone has manually changed the current shader program
bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
void useSimpleProgram();
void useBlitProgram();
void setHasComplexGeometry(bool hasComplexGeometry)
{
complexGeometry = hasComplexGeometry;
shaderProgNeedsChanging = true;
}
bool hasComplexGeometry() const
{
return complexGeometry;
}
QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
QGLEngineSharedShaders* sharedShaders;
private:
QGLContext* ctx;
bool shaderProgNeedsChanging;
bool complexGeometry;
// Current state variables which influence the choice of shader:
QTransform brushTransform;
int srcPixelType;
OpacityMode opacityMode;
MaskType maskType;
QPainter::CompositionMode compositionMode;
QGLCustomShaderStage* customSrcStage;
QGLEngineShaderProg* currentShaderProg;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif //QGLENGINE_SHADER_MANAGER_H

View file

@ -1,528 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QGL_ENGINE_SHADER_SOURCE_H
#define QGL_ENGINE_SHADER_SOURCE_H
#include "qglengineshadermanager_p.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
static const char* const qglslMainVertexShader = "\n\
void setPosition(); \n\
void main(void) \n\
{ \n\
setPosition(); \n\
}\n";
static const char* const qglslMainWithTexCoordsVertexShader = "\n\
attribute highp vec2 textureCoordArray; \n\
varying highp vec2 textureCoords; \n\
void setPosition(); \n\
void main(void) \n\
{ \n\
setPosition(); \n\
textureCoords = textureCoordArray; \n\
}\n";
static const char* const qglslMainWithTexCoordsAndOpacityVertexShader = "\n\
attribute highp vec2 textureCoordArray; \n\
attribute lowp float opacityArray; \n\
varying highp vec2 textureCoords; \n\
varying lowp float opacity; \n\
void setPosition(); \n\
void main(void) \n\
{ \n\
setPosition(); \n\
textureCoords = textureCoordArray; \n\
opacity = opacityArray; \n\
}\n";
// NOTE: We let GL do the perspective correction so texture lookups in the fragment
// shader are also perspective corrected.
static const char* const qglslPositionOnlyVertexShader = "\n\
attribute highp vec2 vertexCoordsArray; \n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
void setPosition(void) \n\
{ \n\
highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
gl_Position = vec4(transformedPos.xy, 0.0, transformedPos.z); \n\
}\n";
static const char* const qglslComplexGeometryPositionOnlyVertexShader = "\n\
uniform highp mat3 matrix; \n\
attribute highp vec2 vertexCoordsArray; \n\
void setPosition(void) \n\
{ \n\
gl_Position = vec4(matrix * vec3(vertexCoordsArray, 1), 1);\n\
} \n";
static const char* const qglslUntransformedPositionVertexShader = "\n\
attribute highp vec4 vertexCoordsArray; \n\
void setPosition(void) \n\
{ \n\
gl_Position = vertexCoordsArray; \n\
}\n";
// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
static const char* const qglslPositionWithPatternBrushVertexShader = "\n\
attribute highp vec2 vertexCoordsArray; \n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp vec2 invertedTextureSize; \n\
uniform highp mat3 brushTransform; \n\
varying highp vec2 patternTexCoords; \n\
void setPosition(void) \n\
{ \n\
highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1.0); \n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \n\
}\n";
static const char* const qglslAffinePositionWithPatternBrushVertexShader
= qglslPositionWithPatternBrushVertexShader;
static const char* const qglslPatternBrushSrcFragmentShader = "\n\
uniform sampler2D brushTexture; \n\
uniform lowp vec4 patternColor; \n\
varying highp vec2 patternTexCoords;\n\
lowp vec4 srcPixel() \n\
{ \n\
return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \n\
}\n";
// Linear Gradient Brush
static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\n\
attribute highp vec2 vertexCoordsArray; \n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp vec3 linearData; \n\
uniform highp mat3 brushTransform; \n\
varying mediump float index; \n\
void setPosition() \n\
{ \n\
highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \n\
}\n";
static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader
= qglslPositionWithLinearGradientBrushVertexShader;
static const char* const qglslLinearGradientBrushSrcFragmentShader = "\n\
uniform sampler2D brushTexture; \n\
varying mediump float index; \n\
lowp vec4 srcPixel() \n\
{ \n\
mediump vec2 val = vec2(index, 0.5); \n\
return texture2D(brushTexture, val); \n\
}\n";
// Conical Gradient Brush
static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\n\
attribute highp vec2 vertexCoordsArray; \n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp mat3 brushTransform; \n\
varying highp vec2 A; \n\
void setPosition(void) \n\
{ \n\
highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
A = hTexCoords.xy * invertedHTexCoordsZ; \n\
}\n";
static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader
= qglslPositionWithConicalGradientBrushVertexShader;
static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
#define INVERSE_2PI 0.1591549430918953358 \n\
uniform sampler2D brushTexture; \n\
uniform mediump float angle; \n\
varying highp vec2 A; \n\
lowp vec4 srcPixel() \n\
{ \n\
highp float t; \n\
if (abs(A.y) == abs(A.x)) \n\
t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \n\
else \n\
t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \n\
return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \n\
}\n";
// Radial Gradient Brush
static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\n\
attribute highp vec2 vertexCoordsArray;\n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp mat3 brushTransform; \n\
uniform highp vec2 fmp; \n\
uniform 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 qglslAffinePositionWithRadialGradientBrushVertexShader
= qglslPositionWithRadialGradientBrushVertexShader;
static const char* const qglslRadialGradientBrushSrcFragmentShader = "\n\
uniform sampler2D brushTexture; \n\
uniform highp float fmp2_m_radius2; \n\
uniform highp float inverse_2_fmp2_m_radius2; \n\
uniform highp float sqrfr; \n\
varying highp float b; \n\
varying highp vec2 A; \n\
uniform 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 qglslPositionWithTextureBrushVertexShader = "\n\
attribute highp vec2 vertexCoordsArray; \n\
attribute highp vec3 pmvMatrix1; \n\
attribute highp vec3 pmvMatrix2; \n\
attribute highp vec3 pmvMatrix3; \n\
uniform mediump vec2 halfViewportSize; \n\
uniform highp vec2 invertedTextureSize; \n\
uniform highp mat3 brushTransform; \n\
varying highp vec2 brushTextureCoords; \n\
void setPosition(void) \n\
{ \n\
highp mat3 pmvMatrix = mat3(pmvMatrix1, pmvMatrix2, pmvMatrix3); \n\
vec3 transformedPos = pmvMatrix * vec3(vertexCoordsArray.xy, 1.0); \n\
gl_Position.xy = transformedPos.xy / transformedPos.z; \n\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \n\
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \n\
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \n\
gl_Position = vec4(gl_Position.xy * invertedHTexCoordsZ, 0.0, invertedHTexCoordsZ); \n\
brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \n\
}\n";
static const char* const qglslAffinePositionWithTextureBrushVertexShader
= qglslPositionWithTextureBrushVertexShader;
#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 qglslTextureBrushSrcFragmentShader = "\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 qglslTextureBrushSrcFragmentShader = "\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 qglslTextureBrushSrcWithPatternFragmentShader = "\n\
varying highp vec2 brushTextureCoords; \n\
uniform lowp vec4 patternColor; \n\
uniform sampler2D brushTexture; \n\
lowp vec4 srcPixel() \n\
{ \n\
return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \n\
}\n";
// Solid Fill Brush
static const char* const qglslSolidBrushSrcFragmentShader = "\n\
uniform lowp vec4 fragmentColor; \n\
lowp vec4 srcPixel() \n\
{ \n\
return fragmentColor; \n\
}\n";
static const char* const qglslImageSrcFragmentShader = "\n\
varying highp vec2 textureCoords; \n\
uniform sampler2D imageTexture; \n\
lowp vec4 srcPixel() \n\
{ \n"
"return texture2D(imageTexture, textureCoords); \n"
"}\n";
static const char* const qglslCustomSrcFragmentShader = "\n\
varying highp vec2 textureCoords; \n\
uniform sampler2D imageTexture; \n\
lowp vec4 srcPixel() \n\
{ \n\
return customShader(imageTexture, textureCoords); \n\
}\n";
static const char* const qglslImageSrcWithPatternFragmentShader = "\n\
varying highp vec2 textureCoords; \n\
uniform lowp vec4 patternColor; \n\
uniform sampler2D imageTexture; \n\
lowp vec4 srcPixel() \n\
{ \n\
return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \n\
}\n";
static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\n\
varying highp vec2 textureCoords; \n\
uniform sampler2D imageTexture; \n\
lowp vec4 srcPixel() \n\
{ \n\
lowp vec4 sample = texture2D(imageTexture, textureCoords); \n\
sample.rgb = sample.rgb * sample.a; \n\
return sample; \n\
}\n";
static const char* const qglslShockingPinkSrcFragmentShader = "\n\
lowp vec4 srcPixel() \n\
{ \n\
return vec4(0.98, 0.06, 0.75, 1.0); \n\
}\n";
static const char* const qglslMainFragmentShader_ImageArrays = "\n\
varying lowp float opacity; \n\
lowp vec4 srcPixel(); \n\
void main() \n\
{ \n\
gl_FragColor = srcPixel() * opacity; \n\
}\n";
static const char* const qglslMainFragmentShader_CMO = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
lowp vec4 applyMask(lowp vec4); \n\
lowp vec4 compose(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \n\
}\n";
static const char* const qglslMainFragmentShader_CM = "\n\
lowp vec4 srcPixel(); \n\
lowp vec4 applyMask(lowp vec4); \n\
lowp vec4 compose(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = applyMask(compose(srcPixel())); \n\
}\n";
static const char* const qglslMainFragmentShader_MO = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
lowp vec4 applyMask(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = applyMask(srcPixel()*globalOpacity); \n\
}\n";
static const char* const qglslMainFragmentShader_M = "\n\
lowp vec4 srcPixel(); \n\
lowp vec4 applyMask(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = applyMask(srcPixel()); \n\
}\n";
static const char* const qglslMainFragmentShader_CO = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
lowp vec4 compose(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = compose(srcPixel()*globalOpacity); \n\
}\n";
static const char* const qglslMainFragmentShader_C = "\n\
lowp vec4 srcPixel(); \n\
lowp vec4 compose(lowp vec4); \n\
void main() \n\
{ \n\
gl_FragColor = compose(srcPixel()); \n\
}\n";
static const char* const qglslMainFragmentShader_O = "\n\
uniform lowp float globalOpacity; \n\
lowp vec4 srcPixel(); \n\
void main() \n\
{ \n\
gl_FragColor = srcPixel()*globalOpacity; \n\
}\n";
static const char* const qglslMainFragmentShader = "\n\
lowp vec4 srcPixel(); \n\
void main() \n\
{ \n\
gl_FragColor = srcPixel(); \n\
}\n";
static const char* const qglslMaskFragmentShader = "\n\
varying highp vec2 textureCoords;\n\
uniform sampler2D maskTexture;\n\
lowp vec4 applyMask(lowp vec4 src) \n\
{\n\
lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
return src * mask.a; \n\
}\n";
// For source over with subpixel antialiasing, the final color is calculated per component as follows
// (.a is alpha component, .c is red, green or blue component):
// alpha = src.a * mask.c * opacity
// dest.c = dest.c * (1 - alpha) + src.c * alpha
//
// In the first pass, calculate: dest.c = dest.c * (1 - alpha) with blend funcs: zero, 1 - source color
// In the second pass, calculate: dest.c = dest.c + src.c * alpha with blend funcs: one, one
//
// If source is a solid color (src is constant), only the first pass is needed, with blend funcs: constant, 1 - source color
// For source composition with subpixel antialiasing, the final color is calculated per component as follows:
// alpha = src.a * mask.c * opacity
// dest.c = dest.c * (1 - mask.c) + src.c * alpha
//
static const char* const qglslRgbMaskFragmentShaderPass1 = "\n\
varying highp vec2 textureCoords;\n\
uniform sampler2D maskTexture;\n\
lowp vec4 applyMask(lowp vec4 src) \n\
{ \n\
lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
return src.a * mask; \n\
}\n";
static const char* const qglslRgbMaskFragmentShaderPass2 = "\n\
varying highp vec2 textureCoords;\n\
uniform sampler2D maskTexture;\n\
lowp vec4 applyMask(lowp vec4 src) \n\
{ \n\
lowp vec4 mask = texture2D(maskTexture, textureCoords); \n\
return src * mask; \n\
}\n";
/*
Left to implement:
RgbMaskFragmentShader,
RgbMaskWithGammaFragmentShader,
MultiplyCompositionModeFragmentShader,
ScreenCompositionModeFragmentShader,
OverlayCompositionModeFragmentShader,
DarkenCompositionModeFragmentShader,
LightenCompositionModeFragmentShader,
ColorDodgeCompositionModeFragmentShader,
ColorBurnCompositionModeFragmentShader,
HardLightCompositionModeFragmentShader,
SoftLightCompositionModeFragmentShader,
DifferenceCompositionModeFragmentShader,
ExclusionCompositionModeFragmentShader,
*/
QT_END_NAMESPACE
QT_END_HEADER
#endif // GLGC_SHADER_SOURCE_H

View file

@ -1,210 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qglgradientcache_p.h"
#include <qdrawhelper_p.h>
#include <qgl_p.h>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
class QGL2GradientCacheWrapper
{
public:
QGL2GradientCache *cacheForContext(const QGLContext *context) {
QMutexLocker lock(&m_mutex);
return m_resource.value(context);
}
private:
QGLContextGroupResource<QGL2GradientCache> m_resource;
QMutex m_mutex;
};
Q_GLOBAL_STATIC(QGL2GradientCacheWrapper, qt_gradient_caches)
QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context)
{
return qt_gradient_caches()->cacheForContext(context);
}
void QGL2GradientCache::cleanCache()
{
QMutexLocker lock(&m_mutex);
QGLGradientColorTableHash::const_iterator it = cache.constBegin();
for (; it != cache.constEnd(); ++it) {
const CacheInfo &cache_info = it.value();
glDeleteTextures(1, &cache_info.texId);
}
cache.clear();
}
GLuint QGL2GradientCache::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();
QGLGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
if (it == cache.constEnd())
return addCacheElement(hash_val, gradient, opacity);
else {
do {
const CacheInfo &cache_info = it.value();
if (cache_info.stops == stops && cache_info.opacity == opacity
&& cache_info.interpolationMode == gradient.interpolationMode())
{
return cache_info.texId;
}
++it;
} while (it != cache.constEnd() && it.key() == hash_val);
// an exact match for these stops and opacity was not found, create new cache
return addCacheElement(hash_val, gradient, opacity);
}
}
GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
{
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:
QGLGradientColorTableHash::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 QGL2GradientCache::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

View file

@ -1,101 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $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 QGLGRADIENTCACHE_P_H
#define QGLGRADIENTCACHE_P_H
#include <QMultiHash>
#include <QObject>
#include <qgl_p.h>
#include <QtCore/qmutex.h>
QT_BEGIN_NAMESPACE
class QGL2GradientCache
{
struct CacheInfo
{
inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) :
stops(s), opacity(op), interpolationMode(mode) {}
GLuint texId;
QGradientStops stops;
qreal opacity;
QGradient::InterpolationMode interpolationMode;
};
typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash;
public:
static QGL2GradientCache *cacheForContext(const QGLContext *context);
QGL2GradientCache(const QGLContext *) {}
~QGL2GradientCache() { cleanCache(); }
GLuint getBuffer(const QGradient &gradient, qreal opacity);
inline int paletteSize() const { return 1024; }
private:
inline int maxCacheSize() const { return 60; }
inline void generateGradientColorTable(const QGradient& gradient,
uint *colorTable,
int size, qreal opacity) const;
GLuint addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity);
void cleanCache();
QGLGradientColorTableHash cache;
QMutex m_mutex;
};
QT_END_NAMESPACE
#endif // QGLGRADIENTCACHE_P_H

View file

@ -1,456 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QGLSHADERCACHE_MEEGO_P_H
#define QGLSHADERCACHE_MEEGO_P_H
#include <QtCore/qglobal.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(QGLShaderProgram *program, const QGLContext *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 QGLShaderProgram *shader, const QGLContext *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
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(QGLShaderProgram *program, const QGLContext *ctx)
{
if (cacheIndex() == -1)
return false;
return qt_cached_shader(program, ctx, cacheIdx);
}
bool store(QGLShaderProgram *program, const QGLContext *ctx)
{
return qt_cache_shader(program, ctx, md5Sum);
}
private:
QByteArray md5Sum;
int cacheIdx;
};
QT_END_NAMESPACE
#endif
QT_END_HEADER
#endif
#endif

View file

@ -1,97 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#ifndef QGLSHADERCACHE_P_H
#define QGLSHADERCACHE_P_H
#include <QtCore/qglobal.h>
#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2)
# include "qglshadercache_meego_p.h"
#else
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGLShaderProgram;
class QGLContext;
class CachedShader
{
public:
inline CachedShader(const QByteArray &, const QByteArray &)
{}
inline bool isCached()
{
return false;
}
inline bool load(QGLShaderProgram *, const QGLContext *)
{
return false;
}
inline bool store(QGLShaderProgram *, const QGLContext *)
{
return false;
}
};
QT_END_NAMESPACE
QT_END_HEADER
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,338 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGRAPHICSCONTEXT_OPENGL2_P_H
#define QGRAPHICSCONTEXT_OPENGL2_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QDebug>
#include <qpaintengineex_p.h>
#include <qglengineshadermanager_p.h>
#include <qgl2pexvertexarray_p.h>
#include <qglpaintdevice_p.h>
#include <qglpixmapfilter_p.h>
#include <qfontengine_p.h>
#include <qdatabuffer_p.h>
#include <qtriangulatingstroker_p.h>
enum EngineMode {
ImageDrawingMode,
TextDrawingMode,
BrushDrawingMode,
ImageArrayDrawingMode,
ImageArrayWithOpacityDrawingMode
};
QT_BEGIN_NAMESPACE
#define GL_STENCIL_HIGH_BIT GLuint(0x80)
#define QT_BRUSH_TEXTURE_UNIT GLuint(0)
#define QT_IMAGE_TEXTURE_UNIT GLuint(0) //Can be the same as brush texture unit
#define QT_MASK_TEXTURE_UNIT GLuint(1)
#define QT_BACKGROUND_TEXTURE_UNIT GLuint(2)
class QGL2PaintEngineExPrivate;
class QOpenGL2PaintEngineState : public QPainterState
{
public:
QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other);
QOpenGL2PaintEngineState();
~QOpenGL2PaintEngineState();
uint isNew : 1;
uint needsClipBufferClear : 1;
uint clipTestEnabled : 1;
uint canRestoreClip : 1;
uint matrixChanged : 1;
uint compositionModeChanged : 1;
uint opacityChanged : 1;
uint renderHintsChanged : 1;
uint clipChanged : 1;
uint currentClip : 8;
QRect rectangleClip;
};
class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx
{
Q_DECLARE_PRIVATE(QGL2PaintEngineEx)
public:
QGL2PaintEngineEx();
~QGL2PaintEngineEx();
bool begin(QPaintDevice *device);
void ensureActive();
bool end();
virtual void clipEnabledChanged();
virtual void penChanged();
virtual void brushChanged();
virtual void brushOriginChanged();
virtual void opacityChanged();
virtual void compositionModeChanged();
virtual void renderHintsChanged();
virtual void transformChanged();
virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
virtual void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints);
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
virtual void fill(const QVectorPath &path, const QBrush &brush);
virtual void stroke(const QVectorPath &path, const QPen &pen);
virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
virtual void drawStaticTextItem(QStaticTextItem *textItem);
bool drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr);
Type type() const { return OpenGL2; }
virtual void setState(QPainterState *s);
virtual QPainterState *createState(QPainterState *orig) const;
inline QOpenGL2PaintEngineState *state() {
return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
inline const QOpenGL2PaintEngineState *state() const {
return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
void beginNativePainting();
void endNativePainting();
void invalidateState();
QPixmapFilter *pixmapFilter(int type, const QPixmapFilter *prototype);
void setRenderTextActive(bool);
bool isNativePaintingActive() const;
bool supportsTransformations(const qreal, const QTransform &) const { return true; }
private:
Q_DISABLE_COPY(QGL2PaintEngineEx)
};
class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
{
Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
public:
enum StencilFillMode {
OddEvenFillMode,
WindingFillMode,
TriStripStrokeFillMode
};
QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
q(q_ptr),
shaderManager(0),
width(0), height(0),
ctx(0),
useSystemClip(true),
elementIndicesVBOId(0),
opacityArray(0),
snapToPixelGrid(false),
nativePaintingActive(false),
inverseScale(1),
lastMaskTextureUsed(0),
hasCompatibilityExtension(false)
{ }
~QGL2PaintEngineExPrivate();
void updateBrushTexture();
void updateBrushUniforms();
void updateMatrix();
void updateCompositionMode();
void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = -1);
void resetGLState();
// fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
// however writeClip can also be thought of as en entry point as it does similar things.
void fill(const QVectorPath &path);
void stroke(const QVectorPath &path, const QPen &pen);
void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, const QSize &size,
QPainter::PixmapFragmentHints hints);
void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem);
// Calls glVertexAttributePointer if the pointer has changed
inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer);
// draws whatever is in the vertex array:
void drawVertexArrays(const float *data, int *stops, int stopCount, GLenum primitive);
void drawVertexArrays(QGL2PEXVertexArray &vertexArray, GLenum primitive) {
drawVertexArrays((const float *) vertexArray.data(), vertexArray.stops(), vertexArray.stopCount(), primitive);
}
// Composites the bounding rect onto dest buffer:
void composite(const QGLRect& boundingRect);
// Calls drawVertexArrays to render into stencil buffer:
void fillStencilWithVertexArray(const float *data, int count, int *stops, int stopCount, const QGLRect &bounds, StencilFillMode mode);
void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) {
fillStencilWithVertexArray((const float *) vertexArray.data(), 0, vertexArray.stops(), vertexArray.stopCount(),
vertexArray.boundingRect(),
useWindingFill ? WindingFillMode : OddEvenFillMode);
}
void setBrush(const QBrush& brush);
void transferMode(EngineMode newMode);
bool prepareForDraw(bool srcPixelsAreOpaque); // returns true if the program has changed
inline void useSimpleShader();
inline GLuint location(const QGLEngineShaderManager::Uniform uniform) {
return shaderManager->getUniformLocation(uniform);
}
void clearClip(uint value);
void writeClip(const QVectorPath &path, uint value);
void resetClipIfNeeded();
void updateClipScissorTest();
void setScissor(const QRect &rect);
void regenerateClip();
void systemStateChanged();
static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; }
static QGL2PaintEngineExPrivate *getData(QGL2PaintEngineEx *engine) { return engine->d_func(); }
static void cleanupVectorPath(QPaintEngineEx *engine, void *data);
QGL2PaintEngineEx* q;
QGLEngineShaderManager* shaderManager;
QGLPaintDevice* device;
int width, height;
QGLContext *ctx;
EngineMode mode;
bool imageDrawingMode;
QFontEngineGlyphCache::Type glyphCacheType;
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
bool compositionModeDirty;
bool brushTextureDirty;
bool brushUniformsDirty;
bool opacityUniformDirty;
bool matrixUniformDirty;
bool stencilClean; // Has the stencil not been used for clipping so far?
bool useSystemClip;
QRegion dirtyStencilRegion;
QRect currentScissorBounds;
uint maxClip;
QBrush currentBrush; // May not be the state's brush!
const QBrush noBrush;
QPixmap currentBrushPixmap;
QGL2PEXVertexArray vertexCoordinateArray;
QGL2PEXVertexArray textureCoordinateArray;
QVector<GLushort> elementIndices;
GLuint elementIndicesVBOId;
QDataBuffer<GLfloat> opacityArray;
GLfloat staticVertexCoordinateArray[8];
GLfloat staticTextureCoordinateArray[8];
bool snapToPixelGrid;
bool nativePaintingActive;
GLfloat pmvMatrix[3][3];
GLfloat inverseScale;
GLuint lastTextureUsed;
GLuint lastMaskTextureUsed;
bool needsSync;
bool multisamplingAlwaysEnabled;
GLfloat depthRange[2];
float textureInvertedY;
QTriangulatingStroker stroker;
QDashedStrokeProcessor dasher;
QScopedPointer<QPixmapFilter> convolutionFilter;
QScopedPointer<QPixmapFilter> colorizeFilter;
QScopedPointer<QPixmapFilter> blurFilter;
QScopedPointer<QPixmapFilter> dropShadowFilter;
QSet<QVectorPath::CacheEntry *> pathCaches;
QVector<GLuint> unusedVBOSToClean;
QVector<GLuint> unusedIBOSToClean;
const GLfloat *vertexAttribPointers[3];
bool hasCompatibilityExtension;
};
void QGL2PaintEngineExPrivate::setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer)
{
Q_ASSERT(arrayIndex < 3);
if (pointer == vertexAttribPointers[arrayIndex])
return;
vertexAttribPointers[arrayIndex] = pointer;
if (arrayIndex == QT_OPACITY_ATTR)
glVertexAttribPointer(arrayIndex, 1, GL_FLOAT, GL_FALSE, 0, pointer);
else
glVertexAttribPointer(arrayIndex, 2, GL_FLOAT, GL_FALSE, 0, pointer);
}
QT_END_NAMESPACE
#endif

View file

@ -1,396 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtextureglyphcache_gl_p.h"
#include "qpaintengineex_opengl2_p.h"
#include "qglengineshadersource_p.h"
#if defined QT_OPENGL_ES_2 && !defined(QT_NO_EGL)
#include "qeglcontext_p.h"
#endif
QT_BEGIN_NAMESPACE
QAtomicInt qgltextureglyphcache_serial_number = QAtomicInt(1);
QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
: QImageTextureGlyphCache(type, matrix), QGLContextGroupResourceBase()
, ctx(0)
, pex(0)
, m_blitProgram(0)
, m_filterMode(Nearest)
, m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1))
{
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx);
#endif
setContext(context);
m_vertexCoordinateArray[0] = -1.0f;
m_vertexCoordinateArray[1] = -1.0f;
m_vertexCoordinateArray[2] = 1.0f;
m_vertexCoordinateArray[3] = -1.0f;
m_vertexCoordinateArray[4] = 1.0f;
m_vertexCoordinateArray[5] = 1.0f;
m_vertexCoordinateArray[6] = -1.0f;
m_vertexCoordinateArray[7] = 1.0f;
m_textureCoordinateArray[0] = 0.0f;
m_textureCoordinateArray[1] = 0.0f;
m_textureCoordinateArray[2] = 1.0f;
m_textureCoordinateArray[3] = 0.0f;
m_textureCoordinateArray[4] = 1.0f;
m_textureCoordinateArray[5] = 1.0f;
m_textureCoordinateArray[6] = 0.0f;
m_textureCoordinateArray[7] = 1.0f;
}
QGLTextureGlyphCache::~QGLTextureGlyphCache()
{
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
qDebug(" -> ~QGLTextureGlyphCache() %p.", this);
#endif
delete m_blitProgram;
}
void QGLTextureGlyphCache::setContext(const QGLContext *context)
{
ctx = context;
m_h = 0;
}
void QGLTextureGlyphCache::createTextureData(int width, int height)
{
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::createTextureData: Called with no context");
return;
}
// create in QImageTextureGlyphCache baseclass is meant to be called
// only to create the initial image and does not preserve the content,
// so we don't call when this function is called from resize.
if ((!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) && image().isNull())
QImageTextureGlyphCache::createTextureData(width, height);
// Make the lower glyph texture size 16 x 16.
if (width < 16)
width = 16;
if (height < 16)
height = 16;
QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
glGenTextures(1, &glyphTexture->m_texture);
glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
glyphTexture->m_width = width;
glyphTexture->m_height = height;
if (m_type == QFontEngineGlyphCache::Raster_RGBMask) {
QVarLengthArray<uchar> data(width * height * 4);
for (int i = 0; i < data.size(); ++i)
data[i] = 0;
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
} else {
QVarLengthArray<uchar> data(width * height);
for (int i = 0; i < data.size(); ++i)
data[i] = 0;
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
}
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_filterMode = Nearest;
}
void QGLTextureGlyphCache::resizeTextureData(int width, int height)
{
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::resizeTextureData: Called with no context");
return;
}
QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
int oldWidth = glyphTexture->m_width;
int oldHeight = glyphTexture->m_height;
// Make the lower glyph texture size 16 x 16.
if (width < 16)
width = 16;
if (height < 16)
height = 16;
GLuint oldTexture = glyphTexture->m_texture;
createTextureData(width, height);
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::resizeTextureData(width, height);
Q_ASSERT(image().depth() == 8);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, oldHeight, GL_ALPHA, GL_UNSIGNED_BYTE, image().constBits());
glDeleteTextures(1, &oldTexture);
return;
}
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
glBindFramebuffer(GL_FRAMEBUFFER_EXT, glyphTexture->m_fbo);
GLuint tmp_texture;
glGenTextures(1, &tmp_texture);
glBindTexture(GL_TEXTURE_2D, tmp_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, oldWidth, oldHeight, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_filterMode = Nearest;
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, tmp_texture, 0);
glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, oldTexture);
if (pex != 0)
pex->transferMode(BrushDrawingMode);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_BLEND);
glViewport(0, 0, oldWidth, oldHeight);
QGLShaderProgram *blitProgram = 0;
if (pex == 0) {
if (m_blitProgram == 0) {
m_blitProgram = new QGLShaderProgram(ctx);
{
QString source;
source.append(QLatin1String(qglslMainWithTexCoordsVertexShader));
source.append(QLatin1String(qglslUntransformedPositionVertexShader));
QGLShader *vertexShader = new QGLShader(QGLShader::Vertex, m_blitProgram);
vertexShader->compileSourceCode(source);
m_blitProgram->addShader(vertexShader);
}
{
QString source;
source.append(QLatin1String(qglslMainFragmentShader));
source.append(QLatin1String(qglslImageSrcFragmentShader));
QGLShader *fragmentShader = new QGLShader(QGLShader::Fragment, m_blitProgram);
fragmentShader->compileSourceCode(source);
m_blitProgram->addShader(fragmentShader);
}
m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
m_blitProgram->link();
}
glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_vertexCoordinateArray);
glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, m_textureCoordinateArray);
m_blitProgram->bind();
m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));
m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));
m_blitProgram->disableAttributeArray(int(QT_OPACITY_ATTR));
blitProgram = m_blitProgram;
} else {
pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray);
pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray);
pex->shaderManager->useBlitProgram();
blitProgram = pex->shaderManager->blitProgram();
}
blitProgram->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_RENDERBUFFER_EXT, 0);
glDeleteTextures(1, &tmp_texture);
glDeleteTextures(1, &oldTexture);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
if (pex != 0) {
glViewport(0, 0, pex->width, pex->height);
pex->updateClipScissorTest();
}
}
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)
{
if (ctx == 0) {
qWarning("QGLTextureGlyphCache::fillTexture: Called with no context");
return;
}
QGLGlyphTexture *glyphTexture = m_textureResource.value(ctx);
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects() || ctx->d_ptr->workaround_brokenFBOReadBack) {
QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);
glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
const QImage &texture = image();
const uchar *bits = texture.constBits();
bits += c.y * texture.bytesPerLine() + c.x;
for (int i=0; i<c.h; ++i) {
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, c.w, 1, GL_ALPHA, GL_UNSIGNED_BYTE, bits);
bits += texture.bytesPerLine();
}
return;
}
QImage mask = textureMapForGlyph(glyph, subPixelPosition);
const int maskWidth = mask.width();
const int maskHeight = mask.height();
if (mask.format() == QImage::Format_Mono) {
mask = mask.convertToFormat(QImage::Format_Indexed8);
for (int y = 0; y < maskHeight; ++y) {
uchar *src = (uchar *) mask.scanLine(y);
for (int x = 0; x < maskWidth; ++x)
src[x] = -src[x]; // convert 0 and 1 into 0 and 255
}
} else if (mask.format() == QImage::Format_RGB32) {
// Make the alpha component equal to the average of the RGB values.
// This is needed when drawing sub-pixel antialiased text on translucent targets.
for (int y = 0; y < maskHeight; ++y) {
quint32 *src = (quint32 *) mask.scanLine(y);
for (int x = 0; x < maskWidth; ++x) {
uchar r = src[x] >> 16;
uchar g = src[x] >> 8;
uchar b = src[x];
quint32 avg = (quint32(r) + quint32(g) + quint32(b) + 1) / 3; // "+1" for rounding.
src[x] = (src[x] & 0x00ffffff) | (avg << 24);
}
}
}
glBindTexture(GL_TEXTURE_2D, glyphTexture->m_texture);
if (mask.format() == QImage::Format_RGB32) {
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
} else {
// glTexSubImage2D() might cause some garbage to appear in the texture if the mask width is
// not a multiple of four bytes. The bug appeared on a computer with 32-bit Windows Vista
// and nVidia GeForce 8500GT. GL_UNPACK_ALIGNMENT is set to four bytes, 'mask' has a
// multiple of four bytes per line, and most of the glyph shows up correctly in the
// texture, which makes me think that this is a driver bug.
// One workaround is to make sure the mask width is a multiple of four bytes, for instance
// by converting it to a format with four bytes per pixel. Another is to copy one line at a
// time.
if (!ctx->d_ptr->workaround_brokenAlphaTexSubImage_init) {
// don't know which driver versions exhibit this bug, so be conservative for now
const QByteArray vendorString(reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
ctx->d_ptr->workaround_brokenAlphaTexSubImage = vendorString.indexOf("NVIDIA") >= 0;
ctx->d_ptr->workaround_brokenAlphaTexSubImage_init = true;
}
if (ctx->d_ptr->workaround_brokenAlphaTexSubImage) {
for (int i = 0; i < maskHeight; ++i)
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y + i, maskWidth, 1, GL_ALPHA, GL_UNSIGNED_BYTE, mask.scanLine(i));
} else {
glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
}
}
}
int QGLTextureGlyphCache::glyphPadding() const
{
return 1;
}
int QGLTextureGlyphCache::maxTextureWidth() const
{
if (ctx == 0)
return QImageTextureGlyphCache::maxTextureWidth();
else
return ctx->d_ptr->maxTextureSize();
}
int QGLTextureGlyphCache::maxTextureHeight() const
{
if (ctx == 0)
return QImageTextureGlyphCache::maxTextureHeight();
if (ctx->d_ptr->workaround_brokenTexSubImage)
return qMin(1024, ctx->d_ptr->maxTextureSize());
else
return ctx->d_ptr->maxTextureSize();
}
void QGLTextureGlyphCache::clear()
{
if (ctx != 0) {
m_textureResource.cleanup(ctx);
m_w = 0;
m_h = 0;
m_cx = 0;
m_cy = 0;
m_currentRowHeight = 0;
coords.clear();
}
}
QT_END_NAMESPACE

View file

@ -1,172 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTEXTUREGLYPHCACHE_GL_P_H
#define QTEXTUREGLYPHCACHE_GL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists 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.
//
#include <qtextureglyphcache_p.h>
#include <qgl_p.h>
#include <qglshaderprogram.h>
#include <qglframebufferobject.h>
// #define QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
QT_BEGIN_NAMESPACE
class QGL2PaintEngineExPrivate;
struct QGLGlyphTexture
{
QGLGlyphTexture(const QGLContext *ctx)
: m_fbo(0)
, m_width(0)
, m_height(0)
{
if (ctx && QGLFramebufferObject::hasOpenGLFramebufferObjects() && !ctx->d_ptr->workaround_brokenFBOReadBack)
glGenFramebuffers(1, &m_fbo);
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
qDebug(" -> QGLGlyphTexture() %p for context %p.", this, ctx);
#endif
}
~QGLGlyphTexture() {
const QGLContext *ctx = QGLContext::currentContext();
#ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG
qDebug("~QGLGlyphTexture() %p for context %p.", this, ctx);
#endif
// At this point, the context group is made current, so it's safe to
// release resources without a makeCurrent() call
if (ctx) {
if (m_fbo)
glDeleteFramebuffers(1, &m_fbo);
if (m_width || m_height)
glDeleteTextures(1, &m_texture);
}
}
GLuint m_texture;
GLuint m_fbo;
int m_width;
int m_height;
};
class Q_OPENGL_EXPORT QGLTextureGlyphCache : public QImageTextureGlyphCache, public QGLContextGroupResourceBase
{
public:
QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix);
~QGLTextureGlyphCache();
virtual void createTextureData(int width, int height);
virtual void resizeTextureData(int width, int height);
virtual void fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition);
virtual int glyphPadding() const;
virtual int maxTextureWidth() const;
virtual int maxTextureHeight() const;
inline GLuint texture() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
return glyphTexture ? glyphTexture->m_texture : 0;
}
inline int width() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
return glyphTexture ? glyphTexture->m_width : 0;
}
inline int height() const {
QGLTextureGlyphCache *that = const_cast<QGLTextureGlyphCache *>(this);
QGLGlyphTexture *glyphTexture = that->m_textureResource.value(ctx);
return glyphTexture ? glyphTexture->m_height : 0;
}
inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
void setContext(const QGLContext *context);
inline const QGLContext *context() const { return ctx; }
inline int serialNumber() const { return m_serialNumber; }
enum FilterMode {
Nearest,
Linear
};
FilterMode filterMode() const { return m_filterMode; }
void setFilterMode(FilterMode m) { m_filterMode = m; }
void clear();
void contextDeleted(const QGLContext *context) {
if (ctx == context)
ctx = 0;
}
void freeResource(void *) { ctx = 0; }
private:
QGLContextGroupResource<QGLGlyphTexture> m_textureResource;
const QGLContext *ctx;
QGL2PaintEngineExPrivate *pex;
QGLShaderProgram *m_blitProgram;
FilterMode m_filterMode;
GLfloat m_vertexCoordinateArray[8];
GLfloat m_textureCoordinateArray[8];
int m_serialNumber;
};
QT_END_NAMESPACE
#endif

View file

@ -1,590 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtriangulatingstroker_p.h"
#include <qmath.h>
QT_BEGIN_NAMESPACE
#define CURVE_FLATNESS Q_PI / 8
void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal *cur,
bool implicitClose, bool endsAtStart)
{
if (endsAtStart) {
join(start + 2);
} else if (implicitClose) {
join(start);
lineTo(start);
join(start+2);
} else {
endCap(cur);
}
int count = m_vertices.size();
// Copy the (x, y) values because QDataBuffer::add(const float& t)
// may resize the buffer, which will leave t pointing at the
// previous buffer's memory region if we don't copy first.
float x = m_vertices.at(count-2);
float y = m_vertices.at(count-1);
m_vertices.add(x);
m_vertices.add(y);
}
void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &)
{
const qreal *pts = path.points();
const QPainterPath::ElementType *types = path.elements();
int count = path.elementCount();
if (count < 2)
return;
const qreal penWidth = pen.widthF();
float realWidth = penWidth;
if (realWidth == 0)
realWidth = 1;
m_width = realWidth / 2;
bool cosmetic = pen.isCosmetic();
if (cosmetic) {
m_width = m_width * m_inv_scale;
}
m_join_style = pen.joinStyle();
m_cap_style = pen.capStyle();
m_vertices.reset();
m_miter_limit = pen.miterLimit() * penWidth;
// The curvyness is based on the notion that I originally wanted
// roughly one line segment pr 4 pixels. This may seem little, but
// because we sample at constantly incrementing B(t) E [0<t<1], we
// will get longer segments where the curvature is small and smaller
// segments when the curvature is high.
//
// To get a rough idea of the length of each curve, I pretend that
// the curve is a 90 degree arc, whose radius is
// qMax(curveBounds.width, curveBounds.height). Based on this
// logic we can estimate the length of the outline edges based on
// the radius + a pen width and adjusting for scale factors
// depending on if the pen is cosmetic or not.
//
// The curvyness value of PI/14 was based on,
// arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere
// between 3 and 8 where 5 seemed to be give pretty good results
// hence: Q_PI/14. Lower divisors will give more detail at the
// direct cost of performance.
// simplfy pens that are thin in device size (2px wide or less)
if (realWidth < 2.5 && (cosmetic || m_inv_scale == 1)) {
if (m_cap_style == Qt::RoundCap)
m_cap_style = Qt::SquareCap;
if (m_join_style == Qt::RoundJoin)
m_join_style = Qt::MiterJoin;
m_curvyness_add = 0.5;
m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;
m_roundness = 1;
} else if (cosmetic) {
m_curvyness_add = realWidth / 2;
m_curvyness_mul = CURVE_FLATNESS;
m_roundness = qMax<int>(4, realWidth * CURVE_FLATNESS);
} else {
m_curvyness_add = m_width;
m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;
m_roundness = qMax<int>(4, realWidth * m_curvyness_mul);
}
// Over this level of segmentation, there doesn't seem to be any
// benefit, even for huge penWidth
if (m_roundness > 24)
m_roundness = 24;
m_sin_theta = qFastSin(Q_PI / m_roundness);
m_cos_theta = qFastCos(Q_PI / m_roundness);
const qreal *endPts = pts + (count<<1);
const qreal *startPts = 0;
Qt::PenCapStyle cap = m_cap_style;
if (!types) {
// skip duplicate points
while((pts + 2) < endPts && pts[0] == pts[2] && pts[1] == pts[3])
pts += 2;
if ((pts + 2) == endPts)
return;
startPts = pts;
bool endsAtStart = startPts[0] == *(endPts-2) && startPts[1] == *(endPts-1);
if (endsAtStart || path.hasImplicitClose())
m_cap_style = Qt::FlatCap;
moveTo(pts);
m_cap_style = cap;
pts += 2;
lineTo(pts);
pts += 2;
while (pts < endPts) {
if (m_cx != pts[0] || m_cy != pts[1]) {
join(pts);
lineTo(pts);
}
pts += 2;
}
endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);
} else {
bool endsAtStart = false;
while (pts < endPts) {
switch (*types) {
case QPainterPath::MoveToElement: {
if (pts != path.points())
endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);
startPts = pts;
int end = (endPts - pts) / 2;
int i = 2; // Start looking to ahead since we never have two moveto's in a row
while (i<end && types[i] != QPainterPath::MoveToElement) {
++i;
}
endsAtStart = startPts[0] == pts[i*2 - 2] && startPts[1] == pts[i*2 - 1];
if (endsAtStart || path.hasImplicitClose())
m_cap_style = Qt::FlatCap;
moveTo(pts);
m_cap_style = cap;
pts+=2;
++types;
break; }
case QPainterPath::LineToElement:
if (*(types - 1) != QPainterPath::MoveToElement)
join(pts);
lineTo(pts);
pts+=2;
++types;
break;
case QPainterPath::CurveToElement:
if (*(types - 1) != QPainterPath::MoveToElement)
join(pts);
cubicTo(pts);
pts+=6;
types+=3;
break;
default:
Q_ASSERT(false);
break;
}
}
endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);
}
}
void QTriangulatingStroker::moveTo(const qreal *pts)
{
m_cx = pts[0];
m_cy = pts[1];
float x2 = pts[2];
float y2 = pts[3];
normalVector(m_cx, m_cy, x2, y2, &m_nvx, &m_nvy);
// To acheive jumps we insert zero-area tringles. This is done by
// adding two identical points in both the end of previous strip
// and beginning of next strip
bool invisibleJump = m_vertices.size();
switch (m_cap_style) {
case Qt::FlatCap:
if (invisibleJump) {
m_vertices.add(m_cx + m_nvx);
m_vertices.add(m_cy + m_nvy);
}
break;
case Qt::SquareCap: {
float sx = m_cx - m_nvy;
float sy = m_cy + m_nvx;
if (invisibleJump) {
m_vertices.add(sx + m_nvx);
m_vertices.add(sy + m_nvy);
}
emitLineSegment(sx, sy, m_nvx, m_nvy);
break; }
case Qt::RoundCap: {
QVarLengthArray<float> points;
arcPoints(m_cx, m_cy, m_cx + m_nvx, m_cy + m_nvy, m_cx - m_nvx, m_cy - m_nvy, points);
m_vertices.resize(m_vertices.size() + points.size() + 2 * int(invisibleJump));
int count = m_vertices.size();
int front = 0;
int end = points.size() / 2;
while (front != end) {
m_vertices.at(--count) = points[2 * end - 1];
m_vertices.at(--count) = points[2 * end - 2];
--end;
if (front == end)
break;
m_vertices.at(--count) = points[2 * front + 1];
m_vertices.at(--count) = points[2 * front + 0];
++front;
}
if (invisibleJump) {
m_vertices.at(count - 1) = m_vertices.at(count + 1);
m_vertices.at(count - 2) = m_vertices.at(count + 0);
}
break; }
default: break; // ssssh gcc...
}
emitLineSegment(m_cx, m_cy, m_nvx, m_nvy);
}
void QTriangulatingStroker::cubicTo(const qreal *pts)
{
const QPointF *p = (const QPointF *) pts;
QBezier bezier = QBezier::fromPoints(*(p - 1), p[0], p[1], p[2]);
QRectF bounds = bezier.bounds();
float rad = qMax(bounds.width(), bounds.height());
int threshold = qMin<float>(64, (rad + m_curvyness_add) * m_curvyness_mul);
if (threshold < 4)
threshold = 4;
qreal threshold_minus_1 = threshold - 1;
float vx, vy;
float cx = m_cx, cy = m_cy;
float x, y;
for (int i=1; i<threshold; ++i) {
qreal t = qreal(i) / threshold_minus_1;
QPointF p = bezier.pointAt(t);
x = p.x();
y = p.y();
normalVector(cx, cy, x, y, &vx, &vy);
emitLineSegment(x, y, vx, vy);
cx = x;
cy = y;
}
m_cx = cx;
m_cy = cy;
m_nvx = vx;
m_nvy = vy;
}
void QTriangulatingStroker::join(const qreal *pts)
{
// Creates a join to the next segment (m_cx, m_cy) -> (pts[0], pts[1])
normalVector(m_cx, m_cy, pts[0], pts[1], &m_nvx, &m_nvy);
switch (m_join_style) {
case Qt::BevelJoin:
break;
case Qt::SvgMiterJoin:
case Qt::MiterJoin: {
// Find out on which side the join should be.
int count = m_vertices.size();
float prevNvx = m_vertices.at(count - 2) - m_cx;
float prevNvy = m_vertices.at(count - 1) - m_cy;
float xprod = prevNvx * m_nvy - prevNvy * m_nvx;
float px, py, qx, qy;
// If the segments are parallel, use bevel join.
if (qFuzzyIsNull(xprod))
break;
// Find the corners of the previous and next segment to join.
if (xprod < 0) {
px = m_vertices.at(count - 2);
py = m_vertices.at(count - 1);
qx = m_cx - m_nvx;
qy = m_cy - m_nvy;
} else {
px = m_vertices.at(count - 4);
py = m_vertices.at(count - 3);
qx = m_cx + m_nvx;
qy = m_cy + m_nvy;
}
// Find intersection point.
float pu = px * prevNvx + py * prevNvy;
float qv = qx * m_nvx + qy * m_nvy;
float ix = (m_nvy * pu - prevNvy * qv) / xprod;
float iy = (prevNvx * qv - m_nvx * pu) / xprod;
// Check that the distance to the intersection point is less than the miter limit.
if ((ix - px) * (ix - px) + (iy - py) * (iy - py) <= m_miter_limit * m_miter_limit) {
m_vertices.add(ix);
m_vertices.add(iy);
m_vertices.add(ix);
m_vertices.add(iy);
}
// else
// Do a plain bevel join if the miter limit is exceeded or if
// the lines are parallel. This is not what the raster
// engine's stroker does, but it is both faster and similar to
// what some other graphics API's do.
break; }
case Qt::RoundJoin: {
QVarLengthArray<float> points;
int count = m_vertices.size();
float prevNvx = m_vertices.at(count - 2) - m_cx;
float prevNvy = m_vertices.at(count - 1) - m_cy;
if (m_nvx * prevNvy - m_nvy * prevNvx < 0) {
arcPoints(0, 0, m_nvx, m_nvy, -prevNvx, -prevNvy, points);
for (int i = points.size() / 2; i > 0; --i)
emitLineSegment(m_cx, m_cy, points[2 * i - 2], points[2 * i - 1]);
} else {
arcPoints(0, 0, -prevNvx, -prevNvy, m_nvx, m_nvy, points);
for (int i = 0; i < points.size() / 2; ++i)
emitLineSegment(m_cx, m_cy, points[2 * i + 0], points[2 * i + 1]);
}
break; }
default: break; // gcc warn--
}
emitLineSegment(m_cx, m_cy, m_nvx, m_nvy);
}
void QTriangulatingStroker::endCap(const qreal *)
{
switch (m_cap_style) {
case Qt::FlatCap:
break;
case Qt::SquareCap:
emitLineSegment(m_cx + m_nvy, m_cy - m_nvx, m_nvx, m_nvy);
break;
case Qt::RoundCap: {
QVarLengthArray<float> points;
int count = m_vertices.size();
arcPoints(m_cx, m_cy, m_vertices.at(count - 2), m_vertices.at(count - 1), m_vertices.at(count - 4), m_vertices.at(count - 3), points);
int front = 0;
int end = points.size() / 2;
while (front != end) {
m_vertices.add(points[2 * end - 2]);
m_vertices.add(points[2 * end - 1]);
--end;
if (front == end)
break;
m_vertices.add(points[2 * front + 0]);
m_vertices.add(points[2 * front + 1]);
++front;
}
break; }
default: break; // to shut gcc up...
}
}
void QTriangulatingStroker::arcPoints(float cx, float cy, float fromX, float fromY, float toX, float toY, QVarLengthArray<float> &points)
{
float dx1 = fromX - cx;
float dy1 = fromY - cy;
float dx2 = toX - cx;
float dy2 = toY - cy;
// while more than 180 degrees left:
while (dx1 * dy2 - dx2 * dy1 < 0) {
float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
dx1 = tmpx;
dy1 = tmpy;
points.append(cx + dx1);
points.append(cy + dy1);
}
// while more than 90 degrees left:
while (dx1 * dx2 + dy1 * dy2 < 0) {
float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
dx1 = tmpx;
dy1 = tmpy;
points.append(cx + dx1);
points.append(cy + dy1);
}
// while more than 0 degrees left:
while (dx1 * dy2 - dx2 * dy1 > 0) {
float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;
float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;
dx1 = tmpx;
dy1 = tmpy;
points.append(cx + dx1);
points.append(cy + dy1);
}
// remove last point which was rotated beyond [toX, toY].
if (!points.isEmpty())
points.resize(points.size() - 2);
}
static void qdashprocessor_moveTo(qreal x, qreal y, void *data)
{
((QDashedStrokeProcessor *) data)->addElement(QPainterPath::MoveToElement, x, y);
}
static void qdashprocessor_lineTo(qreal x, qreal y, void *data)
{
((QDashedStrokeProcessor *) data)->addElement(QPainterPath::LineToElement, x, y);
}
static void qdashprocessor_cubicTo(qreal, qreal, qreal, qreal, qreal, qreal, void *)
{
Q_ASSERT(0); // The dasher should not produce curves...
}
QDashedStrokeProcessor::QDashedStrokeProcessor()
: m_points(0), m_types(0),
m_dash_stroker(0), m_inv_scale(1)
{
m_dash_stroker.setMoveToHook(qdashprocessor_moveTo);
m_dash_stroker.setLineToHook(qdashprocessor_lineTo);
m_dash_stroker.setCubicToHook(qdashprocessor_cubicTo);
}
void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, const QRectF &clip)
{
const qreal *pts = path.points();
const QPainterPath::ElementType *types = path.elements();
int count = path.elementCount();
bool cosmetic = pen.isCosmetic();
m_points.reset();
m_types.reset();
m_points.reserve(path.elementCount());
m_types.reserve(path.elementCount());
qreal width = pen.widthF();
if (width == 0)
width = 1;
m_dash_stroker.setDashPattern(pen.dashPattern());
m_dash_stroker.setStrokeWidth(cosmetic ? width * m_inv_scale : width);
m_dash_stroker.setDashOffset(pen.dashOffset());
m_dash_stroker.setMiterLimit(pen.miterLimit());
m_dash_stroker.setClipRect(clip);
float curvynessAdd, curvynessMul;
// simplfy pens that are thin in device size (2px wide or less)
if (width < 2.5 && (cosmetic || m_inv_scale == 1)) {
curvynessAdd = 0.5;
curvynessMul = CURVE_FLATNESS / m_inv_scale;
} else if (cosmetic) {
curvynessAdd= width / 2;
curvynessMul= CURVE_FLATNESS;
} else {
curvynessAdd = width * m_inv_scale;
curvynessMul = CURVE_FLATNESS / m_inv_scale;
}
if (count < 2)
return;
const qreal *endPts = pts + (count<<1);
m_dash_stroker.begin(this);
if (!types) {
m_dash_stroker.moveTo(pts[0], pts[1]);
pts += 2;
while (pts < endPts) {
m_dash_stroker.lineTo(pts[0], pts[1]);
pts += 2;
}
} else {
while (pts < endPts) {
switch (*types) {
case QPainterPath::MoveToElement:
m_dash_stroker.moveTo(pts[0], pts[1]);
pts += 2;
++types;
break;
case QPainterPath::LineToElement:
m_dash_stroker.lineTo(pts[0], pts[1]);
pts += 2;
++types;
break;
case QPainterPath::CurveToElement: {
QBezier b = QBezier::fromPoints(*(((const QPointF *) pts) - 1),
*(((const QPointF *) pts)),
*(((const QPointF *) pts) + 1),
*(((const QPointF *) pts) + 2));
QRectF bounds = b.bounds();
float rad = qMax(bounds.width(), bounds.height());
int threshold = qMin<float>(64, (rad + curvynessAdd) * curvynessMul);
if (threshold < 4)
threshold = 4;
qreal threshold_minus_1 = threshold - 1;
for (int i=0; i<threshold; ++i) {
QPointF pt = b.pointAt(i / threshold_minus_1);
m_dash_stroker.lineTo(pt.x(), pt.y());
}
pts += 6;
types += 3;
break; }
default: break;
}
}
}
m_dash_stroker.end();
}
QT_END_NAMESPACE

View file

@ -1,158 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTRIANGULATINGSTROKER_P_H
#define QTRIANGULATINGSTROKER_P_H
#include <qdatabuffer_p.h>
#include <qvarlengtharray.h>
#include <qvectorpath_p.h>
#include <qbezier_p.h>
#include <qmath.h>
#include <qmath_p.h>
#include <qstroker_p.h>
QT_BEGIN_NAMESPACE
class QTriangulatingStroker
{
public:
QTriangulatingStroker() : m_vertices(0) {}
void process(const QVectorPath &path, const QPen &pen, const QRectF &clip);
inline int vertexCount() const { return m_vertices.size(); }
inline const float *vertices() const { return m_vertices.data(); }
inline void setInvScale(qreal invScale) { m_inv_scale = invScale; }
private:
inline void emitLineSegment(float x, float y, float nx, float ny);
void moveTo(const qreal *pts);
inline void lineTo(const qreal *pts);
void cubicTo(const qreal *pts);
void join(const qreal *pts);
inline void normalVector(float x1, float y1, float x2, float y2, float *nx, float *ny);
void endCap(const qreal *pts);
void arcPoints(float cx, float cy, float fromX, float fromY, float toX, float toY, QVarLengthArray<float> &points);
void endCapOrJoinClosed(const qreal *start, const qreal *cur, bool implicitClose, bool endsAtStart);
QDataBuffer<float> m_vertices;
float m_cx, m_cy; // current points
float m_nvx, m_nvy; // normal vector...
float m_width;
qreal m_miter_limit;
int m_roundness; // Number of line segments in a round join
qreal m_sin_theta; // sin(m_roundness / 360);
qreal m_cos_theta; // cos(m_roundness / 360);
qreal m_inv_scale;
float m_curvyness_mul;
float m_curvyness_add;
Qt::PenJoinStyle m_join_style;
Qt::PenCapStyle m_cap_style;
};
class QDashedStrokeProcessor
{
public:
QDashedStrokeProcessor();
void process(const QVectorPath &path, const QPen &pen, const QRectF &clip);
inline void addElement(QPainterPath::ElementType type, qreal x, qreal y) {
m_points.add(x);
m_points.add(y);
m_types.add(type);
}
inline int elementCount() const { return m_types.size(); }
inline qreal *points() const { return m_points.data(); }
inline QPainterPath::ElementType *elementTypes() const { return m_types.data(); }
inline void setInvScale(qreal invScale) { m_inv_scale = invScale; }
private:
QDataBuffer<qreal> m_points;
QDataBuffer<QPainterPath::ElementType> m_types;
QDashStroker m_dash_stroker;
qreal m_inv_scale;
};
inline void QTriangulatingStroker::normalVector(float x1, float y1, float x2, float y2,
float *nx, float *ny)
{
float dx = x2 - x1;
float dy = y2 - y1;
float pw;
if (dx == 0)
pw = m_width / qAbs(dy);
else if (dy == 0)
pw = m_width / qAbs(dx);
else
pw = m_width / sqrt(dx*dx + dy*dy);
*nx = -dy * pw;
*ny = dx * pw;
}
inline void QTriangulatingStroker::emitLineSegment(float x, float y, float vx, float vy)
{
m_vertices.add(x + vx);
m_vertices.add(y + vy);
m_vertices.add(x - vx);
m_vertices.add(y - vy);
}
void QTriangulatingStroker::lineTo(const qreal *pts)
{
emitLineSegment(pts[0], pts[1], m_nvx, m_nvy);
m_cx = pts[0];
m_cy = pts[1];
}
QT_END_NAMESPACE
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,148 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTRIANGULATOR_P_H
#define QTRIANGULATOR_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtCore/qvector.h>
#include <QtGui/qvectorpath_p.h>
QT_BEGIN_NAMESPACE
class QVertexIndexVector
{
public:
enum Type {
UnsignedInt,
UnsignedShort
};
inline Type type() const { return t; }
inline void setDataUint(const QVector<quint32> &data)
{
t = UnsignedInt;
indices32 = data;
}
inline void setDataUshort(const QVector<quint16> &data)
{
t = UnsignedShort;
indices16 = data;
}
inline const void* data() const
{
if (t == UnsignedInt)
return indices32.data();
return indices16.data();
}
inline int size() const
{
if (t == UnsignedInt)
return indices32.size();
return indices16.size();
}
inline QVertexIndexVector &operator = (const QVertexIndexVector &other)
{
if (t == UnsignedInt)
indices32 = other.indices32;
else
indices16 = other.indices16;
return *this;
}
private:
Type t;
QVector<quint32> indices32;
QVector<quint16> indices16;
};
struct QTriangleSet
{
inline QTriangleSet() { }
inline QTriangleSet(const QTriangleSet &other) : vertices(other.vertices), indices(other.indices) { }
QTriangleSet &operator = (const QTriangleSet &other) {vertices = other.vertices; indices = other.indices; return *this;}
// The vertices of a triangle are given by: (x[i[n]], y[i[n]]), (x[j[n]], y[j[n]]), (x[k[n]], y[k[n]]), n = 0, 1, ...
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
QVertexIndexVector indices; // [i[0], j[0], k[0], i[1], j[1], k[1], i[2], ...]
};
struct QPolylineSet
{
inline QPolylineSet() { }
inline QPolylineSet(const QPolylineSet &other) : vertices(other.vertices), indices(other.indices) { }
QPolylineSet &operator = (const QPolylineSet &other) {vertices = other.vertices; indices = other.indices; return *this;}
QVector<qreal> vertices; // [x[0], y[0], x[1], y[1], x[2], ...]
QVertexIndexVector indices;
};
// The vertex coordinates of the returned triangle set will be rounded to a grid with a mesh size
// of 1/32. The polygon is first transformed, then scaled by 32, the coordinates are rounded to
// integers, the polygon is triangulated, and then scaled back by 1/32.
// 'hint' should be a combination of QVectorPath::Hints.
// 'lod' is the level of detail. Default is 1. Curves are split into more lines when 'lod' is higher.
QTriangleSet qTriangulate(const qreal *polygon, int count, uint hint = QVectorPath::PolygonHint | QVectorPath::OddEvenFill, const QTransform &matrix = QTransform());
QTriangleSet qTriangulate(const QVectorPath &path, const QTransform &matrix = QTransform(), qreal lod = 1);
QTriangleSet qTriangulate(const QPainterPath &path, const QTransform &matrix = QTransform(), qreal lod = 1);
QPolylineSet qPolyline(const QVectorPath &path, const QTransform &matrix = QTransform(), qreal lod = 1);
QPolylineSet qPolyline(const QPainterPath &path, const QTransform &matrix = QTransform(), qreal lod = 1);
QT_END_NAMESPACE
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,543 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGL_H
#define QGL_H
#include <QtGui/qwidget.h>
#include <QtGui/qpaintengine.h>
#include <QtOpenGL/qglcolormap.h>
#include <QtCore/qmap.h>
#include <QtCore/qscopedpointer.h>
QT_BEGIN_HEADER
#if defined(QT_OPENGL_ES_1)
# include <GLES/gl.h>
# ifndef GL_DOUBLE
# define GL_DOUBLE GL_FLOAT
# endif
# ifndef GLdouble
typedef GLfloat GLdouble;
# endif
#elif defined(QT_OPENGL_ES_2)
# include <GLES2/gl2.h>
# ifndef GL_DOUBLE
# define GL_DOUBLE GL_FLOAT
# endif
# ifndef GLdouble
typedef GLfloat GLdouble;
# endif
#else
# include <GL/gl.h>
#endif
QT_BEGIN_NAMESPACE
class QPixmap;
#if defined(Q_WS_X11) && !defined(QT_OPENGL_ES)
class QGLOverlayWidget;
#endif
class QGLWidgetPrivate;
class QGLContextPrivate;
// Namespace class:
namespace QGL
{
Q_OPENGL_EXPORT void setPreferredPaintEngine(QPaintEngine::Type engineType);
enum FormatOption {
DoubleBuffer = 0x0001,
DepthBuffer = 0x0002,
Rgba = 0x0004,
AlphaChannel = 0x0008,
AccumBuffer = 0x0010,
StencilBuffer = 0x0020,
StereoBuffers = 0x0040,
DirectRendering = 0x0080,
HasOverlay = 0x0100,
SampleBuffers = 0x0200,
DeprecatedFunctions = 0x0400,
SingleBuffer = DoubleBuffer << 16,
NoDepthBuffer = DepthBuffer << 16,
ColorIndex = Rgba << 16,
NoAlphaChannel = AlphaChannel << 16,
NoAccumBuffer = AccumBuffer << 16,
NoStencilBuffer = StencilBuffer << 16,
NoStereoBuffers = StereoBuffers << 16,
IndirectRendering = DirectRendering << 16,
NoOverlay = HasOverlay << 16,
NoSampleBuffers = SampleBuffers << 16,
NoDeprecatedFunctions = DeprecatedFunctions << 16
};
Q_DECLARE_FLAGS(FormatOptions, FormatOption)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QGL::FormatOptions)
class QGLFormatPrivate;
class Q_OPENGL_EXPORT QGLFormat
{
public:
QGLFormat();
QGLFormat(QGL::FormatOptions options, int plane = 0);
QGLFormat(const QGLFormat &other);
QGLFormat &operator=(const QGLFormat &other);
~QGLFormat();
void setDepthBufferSize(int size);
int depthBufferSize() const;
void setAccumBufferSize(int size);
int accumBufferSize() const;
void setRedBufferSize(int size);
int redBufferSize() const;
void setGreenBufferSize(int size);
int greenBufferSize() const;
void setBlueBufferSize(int size);
int blueBufferSize() const;
void setAlphaBufferSize(int size);
int alphaBufferSize() const;
void setStencilBufferSize(int size);
int stencilBufferSize() const;
void setSampleBuffers(bool enable);
bool sampleBuffers() const;
void setSamples(int numSamples);
int samples() const;
void setSwapInterval(int interval);
int swapInterval() const;
bool doubleBuffer() const;
void setDoubleBuffer(bool enable);
bool depth() const;
void setDepth(bool enable);
bool rgba() const;
void setRgba(bool enable);
bool alpha() const;
void setAlpha(bool enable);
bool accum() const;
void setAccum(bool enable);
bool stencil() const;
void setStencil(bool enable);
bool stereo() const;
void setStereo(bool enable);
bool directRendering() const;
void setDirectRendering(bool enable);
bool hasOverlay() const;
void setOverlay(bool enable);
int plane() const;
void setPlane(int plane);
void setOption(QGL::FormatOptions opt);
bool testOption(QGL::FormatOptions opt) const;
static QGLFormat defaultFormat();
static void setDefaultFormat(const QGLFormat& f);
static QGLFormat defaultOverlayFormat();
static void setDefaultOverlayFormat(const QGLFormat& f);
static bool hasOpenGL();
static bool hasOpenGLOverlays();
void setVersion(int major, int minor);
int majorVersion() const;
int minorVersion() const;
enum OpenGLContextProfile {
NoProfile,
CoreProfile,
CompatibilityProfile
};
void setProfile(OpenGLContextProfile profile);
OpenGLContextProfile profile() const;
enum OpenGLVersionFlag {
OpenGL_Version_None = 0x00000000,
OpenGL_Version_1_1 = 0x00000001,
OpenGL_Version_1_2 = 0x00000002,
OpenGL_Version_1_3 = 0x00000004,
OpenGL_Version_1_4 = 0x00000008,
OpenGL_Version_1_5 = 0x00000010,
OpenGL_Version_2_0 = 0x00000020,
OpenGL_Version_2_1 = 0x00000040,
OpenGL_ES_Common_Version_1_0 = 0x00000080,
OpenGL_ES_CommonLite_Version_1_0 = 0x00000100,
OpenGL_ES_Common_Version_1_1 = 0x00000200,
OpenGL_ES_CommonLite_Version_1_1 = 0x00000400,
OpenGL_ES_Version_2_0 = 0x00000800,
OpenGL_Version_3_0 = 0x00001000,
OpenGL_Version_3_1 = 0x00002000,
OpenGL_Version_3_2 = 0x00004000,
OpenGL_Version_3_3 = 0x00008000,
OpenGL_Version_4_0 = 0x00010000
};
Q_DECLARE_FLAGS(OpenGLVersionFlags, OpenGLVersionFlag)
static OpenGLVersionFlags openGLVersionFlags();
private:
QGLFormatPrivate *d;
void detach();
friend Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
friend Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
#ifndef QT_NO_DEBUG_STREAM
friend Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
#endif
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLFormat::OpenGLVersionFlags)
Q_OPENGL_EXPORT bool operator==(const QGLFormat&, const QGLFormat&);
Q_OPENGL_EXPORT bool operator!=(const QGLFormat&, const QGLFormat&);
#ifndef QT_NO_DEBUG_STREAM
Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QGLFormat &);
#endif
class Q_OPENGL_EXPORT QGLContext
{
Q_DECLARE_PRIVATE(QGLContext)
public:
QGLContext(const QGLFormat& format, QPaintDevice* device);
QGLContext(const QGLFormat& format);
virtual ~QGLContext();
virtual bool create(const QGLContext* shareContext = 0);
bool isValid() const;
bool isSharing() const;
void reset();
static bool areSharing(const QGLContext *context1, const QGLContext *context2);
QGLFormat format() const;
QGLFormat requestedFormat() const;
void setFormat(const QGLFormat& format);
// ### Qt 5: return bools + maybe remove virtuals
virtual void makeCurrent();
virtual void doneCurrent();
virtual void swapBuffers() const;
enum BindOption {
NoBindOption = 0x0000,
InvertedYBindOption = 0x0001,
MipmapBindOption = 0x0002,
PremultipliedAlphaBindOption = 0x0004,
LinearFilteringBindOption = 0x0008,
MemoryManagedBindOption = 0x0010, // internal flag
CanFlipNativePixmapBindOption = 0x0020, // internal flag
DefaultBindOption = LinearFilteringBindOption
| InvertedYBindOption
| MipmapBindOption,
InternalBindOption = MemoryManagedBindOption
| PremultipliedAlphaBindOption
};
Q_DECLARE_FLAGS(BindOptions, BindOption)
GLuint bindTexture(const QImage &image, GLenum target, GLint format,
BindOptions options);
GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
BindOptions options);
GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QString &fileName);
void deleteTexture(GLuint tx_id);
void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
static void setTextureCacheLimit(int size);
static int textureCacheLimit();
void *getProcAddress(const QString &proc) const;
QPaintDevice* device() const;
QColor overlayTransparentColor() const;
static const QGLContext* currentContext();
protected:
virtual bool chooseContext(const QGLContext* shareContext = 0);
#if defined(Q_WS_X11)
virtual void* tryVisual(const QGLFormat& f, int bufDepth = 1);
virtual void* chooseVisual();
#endif
bool deviceIsPixmap() const;
bool windowCreated() const;
void setWindowCreated(bool on);
bool initialized() const;
void setInitialized(bool on);
void generateFontDisplayLists(const QFont & fnt, int listBase); // ### Qt 5: remove
uint colorIndex(const QColor& c) const;
void setValid(bool valid);
void setDevice(QPaintDevice *pDev);
protected:
static QGLContext* currentCtx;
private:
QScopedPointer<QGLContextPrivate> d_ptr;
friend class QGLPixelBuffer;
friend class QGLPixelBufferPrivate;
friend class QGLWidget;
friend class QGLWidgetPrivate;
friend class QGLGlyphCache;
friend class QOpenGLPaintEngine;
friend class QOpenGLPaintEnginePrivate;
friend class QGL2PaintEngineEx;
friend class QGL2PaintEngineExPrivate;
friend class QGLEngineShaderManager;
friend class QGLWindowSurface;
friend class QGLPixmapData;
friend class QGLPixmapFilterBase;
friend class QGLTextureGlyphCache;
friend struct QGLGlyphTexture;
friend class QGLContextGroup;
friend class QGLSharedResourceGuard;
friend class QGLPixmapBlurFilter;
friend class QGLExtensions;
friend class QGLTexture;
friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
friend class QGLFramebufferObject;
friend class QGLFramebufferObjectPrivate;
friend class QGLFBOGLPaintDevice;
friend class QGLPaintDevice;
friend class QGLWidgetGLPaintDevice;
friend class QX11GLPixmapData;
friend class QX11GLSharedContexts;
friend class QGLContextResourceBase;
private:
Q_DISABLE_COPY(QGLContext)
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLContext::BindOptions)
class Q_OPENGL_EXPORT QGLWidget : public QWidget
{
Q_OBJECT
Q_DECLARE_PRIVATE(QGLWidget)
public:
explicit QGLWidget(QWidget* parent=0,
const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0);
explicit QGLWidget(QGLContext *context, QWidget* parent=0,
const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0);
explicit QGLWidget(const QGLFormat& format, QWidget* parent=0,
const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0);
~QGLWidget();
void qglColor(const QColor& c) const;
void qglClearColor(const QColor& c) const;
bool isValid() const;
bool isSharing() const;
// ### Qt 5: return bools
void makeCurrent();
void doneCurrent();
bool doubleBuffer() const;
void swapBuffers();
QGLFormat format() const;
void setFormat(const QGLFormat& format);
const QGLContext* context() const;
void setContext(QGLContext* context, const QGLContext* shareContext = 0,
bool deleteOldContext = true);
QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
QImage grabFrameBuffer(bool withAlpha = false);
void makeOverlayCurrent();
const QGLContext* overlayContext() const;
static QImage convertToGLFormat(const QImage& img);
void setMouseTracking(bool enable);
const QGLColormap & colormap() const;
void setColormap(const QGLColormap & map);
void renderText(int x, int y, const QString & str,
const QFont & fnt = QFont(), int listBase = 2000);
void renderText(double x, double y, double z, const QString & str,
const QFont & fnt = QFont(), int listBase = 2000);
QPaintEngine *paintEngine() const;
GLuint bindTexture(const QImage &image, GLenum target, GLint format,
QGLContext::BindOptions options);
GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
QGLContext::BindOptions options);
GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D,
GLint format = GL_RGBA);
GLuint bindTexture(const QString &fileName);
void deleteTexture(GLuint tx_id);
void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
public Q_SLOTS:
virtual void updateGL();
virtual void updateOverlayGL();
protected:
bool event(QEvent *);
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
virtual void initializeOverlayGL();
virtual void resizeOverlayGL(int w, int h);
virtual void paintOverlayGL();
void setAutoBufferSwap(bool on);
bool autoBufferSwap() const;
void paintEvent(QPaintEvent*);
void resizeEvent(QResizeEvent*);
virtual void glInit();
virtual void glDraw();
int fontDisplayListBase(const QFont & fnt, int listBase = 2000); // ### Qt 5: remove
private:
Q_DISABLE_COPY(QGLWidget)
friend class QGLDrawable;
friend class QGLPixelBuffer;
friend class QGLPixelBufferPrivate;
friend class QGLContext;
friend class QGLContextPrivate;
friend class QGLOverlayWidget;
friend class QOpenGLPaintEngine;
friend class QGLPaintDevice;
friend class QGLWidgetGLPaintDevice;
};
//
// QGLFormat inline functions
//
inline bool QGLFormat::doubleBuffer() const
{
return testOption(QGL::DoubleBuffer);
}
inline bool QGLFormat::depth() const
{
return testOption(QGL::DepthBuffer);
}
inline bool QGLFormat::rgba() const
{
return testOption(QGL::Rgba);
}
inline bool QGLFormat::alpha() const
{
return testOption(QGL::AlphaChannel);
}
inline bool QGLFormat::accum() const
{
return testOption(QGL::AccumBuffer);
}
inline bool QGLFormat::stencil() const
{
return testOption(QGL::StencilBuffer);
}
inline bool QGLFormat::stereo() const
{
return testOption(QGL::StereoBuffers);
}
inline bool QGLFormat::directRendering() const
{
return testOption(QGL::DirectRendering);
}
inline bool QGLFormat::hasOverlay() const
{
return testOption(QGL::HasOverlay);
}
inline bool QGLFormat::sampleBuffers() const
{
return testOption(QGL::SampleBuffers);
}
QT_END_NAMESPACE
QT_END_HEADER
#endif // QGL_H

View file

@ -1,385 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qdebug.h>
#include <QtOpenGL/qgl.h>
#include <QtOpenGL/qglpixelbuffer.h>
#include "qgl_p.h"
#include "qgl_egl_p.h"
#include "qglpixelbuffer_p.h"
#ifdef Q_WS_X11
#include <QtGui/qpixmap_x11_p.h>
#endif
QT_BEGIN_NAMESPACE
QEglProperties *QGLContextPrivate::extraWindowSurfaceCreationProps = NULL;
void qt_eglproperties_set_glformat(QEglProperties& eglProperties, const QGLFormat& glFormat)
{
int redSize = glFormat.redBufferSize();
int greenSize = glFormat.greenBufferSize();
int blueSize = glFormat.blueBufferSize();
int alphaSize = glFormat.alphaBufferSize();
int depthSize = glFormat.depthBufferSize();
int stencilSize = glFormat.stencilBufferSize();
int sampleCount = glFormat.samples();
bool prefer32Bit = false;
if (prefer32Bit) {
if (glFormat.alpha() && alphaSize <= 0)
alphaSize = 8;
if (glFormat.depth() && depthSize <= 0)
depthSize = 24;
if (glFormat.stencil() && stencilSize <= 0)
stencilSize = 8;
if (glFormat.sampleBuffers() && sampleCount <= 0)
sampleCount = 1;
redSize = redSize > 0 ? redSize : 8;
greenSize = greenSize > 0 ? greenSize : 8;
blueSize = blueSize > 0 ? blueSize : 8;
alphaSize = alphaSize > 0 ? alphaSize : 8;
depthSize = depthSize > 0 ? depthSize : 24;
stencilSize = stencilSize > 0 ? stencilSize : 8;
sampleCount = sampleCount >= 0 ? sampleCount : 4;
} else {
// QGLFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that
// type has been requested. So we must check QGLFormat's booleans too if size is -1:
if (glFormat.alpha() && alphaSize <= 0)
alphaSize = 1;
if (glFormat.depth() && depthSize <= 0)
depthSize = 1;
if (glFormat.stencil() && stencilSize <= 0)
stencilSize = 1;
if (glFormat.sampleBuffers() && sampleCount <= 0)
sampleCount = 1;
// We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide
// the best performance. The EGL config selection algorithm is a bit stange in this regard:
// The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard
// 32-bit configs completely from the selection. So it then comes to the sorting algorithm.
// The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort
// order is special and described as "by larger _total_ number of color bits.". So EGL will
// put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on
// to say "If the requested number of bits in attrib_list for a particular component is 0,
// then the number of bits for that component is not considered". This part of the spec also
// seems to imply that setting the red/green/blue bits to zero means none of the components
// are considered and EGL disregards the entire sorting rule. It then looks to the next
// highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being
// "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are
// put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit,
// we must set the red/green/blue sizes to zero. This has an unfortunate consequence that
// if the application sets the red/green/blue size to 5/6/5 on the QGLFormat, they will
// probably get a 32-bit config, even when there's an RGB565 config available. Oh well.
// Now normalize the values so -1 becomes 0
redSize = redSize > 0 ? redSize : 0;
greenSize = greenSize > 0 ? greenSize : 0;
blueSize = blueSize > 0 ? blueSize : 0;
alphaSize = alphaSize > 0 ? alphaSize : 0;
depthSize = depthSize > 0 ? depthSize : 0;
stencilSize = stencilSize > 0 ? stencilSize : 0;
sampleCount = sampleCount > 0 ? sampleCount : 0;
}
eglProperties.setValue(EGL_RED_SIZE, redSize);
eglProperties.setValue(EGL_GREEN_SIZE, greenSize);
eglProperties.setValue(EGL_BLUE_SIZE, blueSize);
eglProperties.setValue(EGL_ALPHA_SIZE, alphaSize);
eglProperties.setValue(EGL_DEPTH_SIZE, depthSize);
eglProperties.setValue(EGL_STENCIL_SIZE, stencilSize);
eglProperties.setValue(EGL_SAMPLES, sampleCount);
eglProperties.setValue(EGL_SAMPLE_BUFFERS, sampleCount ? 1 : 0);
}
// Updates "format" with the parameters of the selected configuration.
void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config)
{
EGLint redSize = 0;
EGLint greenSize = 0;
EGLint blueSize = 0;
EGLint alphaSize = 0;
EGLint depthSize = 0;
EGLint stencilSize = 0;
EGLint sampleCount = 0;
EGLint level = 0;
EGLDisplay display = QEgl::display();
eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize);
eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize);
eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize);
eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize);
eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize);
eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize);
eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount);
eglGetConfigAttrib(display, config, EGL_LEVEL, &level);
format.setRedBufferSize(redSize);
format.setGreenBufferSize(greenSize);
format.setBlueBufferSize(blueSize);
format.setAlphaBufferSize(alphaSize);
format.setDepthBufferSize(depthSize);
format.setStencilBufferSize(stencilSize);
format.setSamples(sampleCount);
format.setPlane(level);
format.setDirectRendering(true); // All EGL contexts are direct-rendered
format.setRgba(true); // EGL doesn't support colour index rendering
format.setStereo(false); // EGL doesn't support stereo buffers
format.setAccumBufferSize(0); // EGL doesn't support accululation buffers
format.setDoubleBuffer(true); // We don't support single buffered EGL contexts
// Clear the EGL error state because some of the above may
// have errored out because the attribute is not applicable
// to the surface type. Such errors don't matter.
eglGetError();
}
bool QGLFormat::hasOpenGL()
{
return true;
}
void QGLContext::reset()
{
Q_D(QGLContext);
if (!d->valid)
return;
d->cleanup();
doneCurrent();
if (d->eglContext && d->ownsEglContext) {
d->destroyEglSurfaceForDevice();
delete d->eglContext;
}
d->ownsEglContext = false;
d->eglContext = 0;
d->eglSurface = EGL_NO_SURFACE;
d->crWin = false;
d->sharing = false;
d->valid = false;
d->transpColor = QColor();
d->initDone = false;
QGLContextGroup::removeShare(this);
}
void QGLContext::makeCurrent()
{
Q_D(QGLContext);
if (!d->valid || !d->eglContext || d->eglSurfaceForDevice() == EGL_NO_SURFACE) {
qWarning("QGLContext::makeCurrent(): Cannot make invalid context current");
return;
}
if (d->eglContext->makeCurrent(d->eglSurfaceForDevice())) {
QGLContextPrivate::setCurrentContext(this);
if (!d->workaroundsCached) {
d->workaroundsCached = true;
const char *renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
if (!renderer)
return;
if ((strstr(renderer, "SGX") || strstr(renderer, "MBX"))) {
// PowerVR MBX/SGX chips needs to clear all buffers when starting to render
// a new frame, otherwise there will be a performance penalty to pay for
// each frame.
qDebug() << "Found SGX/MBX driver, enabling FullClearOnEveryFrame";
d->workaround_needsFullClearOnEveryFrame = true;
// Older PowerVR SGX drivers (like the one in the N900) have a
// bug which prevents glCopyTexSubImage2D() to work with a POT
// or GL_ALPHA texture bound to an FBO. The only way to
// identify that driver is to check the EGL version number for it.
const char *egl_version = eglQueryString(d->eglContext->display(), EGL_VERSION);
if (egl_version && strstr(egl_version, "1.3")) {
qDebug() << "Found v1.3 driver, enabling brokenFBOReadBack";
d->workaround_brokenFBOReadBack = true;
} else if (egl_version && strstr(egl_version, "1.4")) {
qDebug() << "Found v1.4 driver, enabling brokenTexSubImage";
d->workaround_brokenTexSubImage = true;
// this is a bit complicated; 1.4 version SGX drivers from
// Nokia have fixed the brokenFBOReadBack problem, but
// official drivers from TI haven't, meaning that things
// like the beagleboard are broken unless we hack around it
// - but at the same time, we want to not reduce performance
// by not enabling this elsewhere.
//
// so, let's check for a Nokia-specific addon, and only
// enable if it isn't present.
// (see MeeGo bug #5616)
if (!QEgl::hasExtension("EGL_NOK_image_shared")) {
// no Nokia extension, this is probably a standard SGX
// driver, so enable the workaround
qDebug() << "Found non-Nokia v1.4 driver, enabling brokenFBOReadBack";
d->workaround_brokenFBOReadBack = true;
}
}
} else if (strstr(renderer, "VideoCore III")) {
// Some versions of VideoCore III drivers seem to pollute and use
// stencil buffer when using glScissors even if stencil test is disabled.
// Workaround is to clear stencil buffer before disabling scissoring.
// qDebug() << "Found VideoCore III driver, enabling brokenDisableScissorTest";
d->workaround_brokenScissor = true;
}
}
}
}
void QGLContext::doneCurrent()
{
Q_D(QGLContext);
if (d->eglContext)
d->eglContext->doneCurrent();
QGLContextPrivate::setCurrentContext(0);
}
void QGLContext::swapBuffers() const
{
Q_D(const QGLContext);
if (!d->valid || !d->eglContext)
return;
d->eglContext->swapBuffers(d->eglSurfaceForDevice());
}
void QGLContextPrivate::destroyEglSurfaceForDevice()
{
if (eglSurface != EGL_NO_SURFACE) {
#if defined(Q_WS_X11)
// Make sure we don't call eglDestroySurface on a surface which
// was created for a different winId. This applies only to QGLWidget
// paint device, so make sure this is the one we're operating on
// (as opposed to a QGLWindowSurface use case).
if (paintDevice && paintDevice->devType() == QInternal::Widget) {
QWidget *w = static_cast<QWidget *>(paintDevice);
if (QGLWidget *wgl = qobject_cast<QGLWidget *>(w)) {
if (wgl->d_func()->eglSurfaceWindowId != wgl->winId()) {
qWarning("WARNING: Potential EGL surface leak! Not destroying surface.");
eglSurface = EGL_NO_SURFACE;
return;
}
}
}
#endif
eglDestroySurface(eglContext->display(), eglSurface);
eglSurface = EGL_NO_SURFACE;
}
}
EGLSurface QGLContextPrivate::eglSurfaceForDevice() const
{
// If a QPixmapData had to create the QGLContext, we don't have a paintDevice
if (!paintDevice)
return eglSurface;
#ifdef Q_WS_X11
if (paintDevice->devType() == QInternal::Pixmap) {
QPixmapData *pmd = static_cast<QPixmap*>(paintDevice)->data_ptr().data();
if (pmd->classId() == QPixmapData::X11Class) {
QX11PixmapData* x11PixmapData = static_cast<QX11PixmapData*>(pmd);
return (EGLSurface)x11PixmapData->gl_surface;
}
}
#endif
if (paintDevice->devType() == QInternal::Pbuffer) {
QGLPixelBuffer* pbuf = static_cast<QGLPixelBuffer*>(paintDevice);
return pbuf->d_func()->pbuf;
}
return eglSurface;
}
void QGLContextPrivate::swapRegion(const QRegion &region)
{
if (!valid || !eglContext)
return;
eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), &region);
}
void QGLContextPrivate::setExtraWindowSurfaceCreationProps(QEglProperties *props)
{
extraWindowSurfaceCreationProps = props;
}
void QGLWidget::setMouseTracking(bool enable)
{
QWidget::setMouseTracking(enable);
}
QColor QGLContext::overlayTransparentColor() const
{
return d_func()->transpColor;
}
uint QGLContext::colorIndex(const QColor &c) const
{
Q_UNUSED(c);
return 0;
}
void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase)
{
Q_UNUSED(fnt);
Q_UNUSED(listBase);
}
void *QGLContext::getProcAddress(const QString &proc) const
{
return (void*)eglGetProcAddress(reinterpret_cast<const char *>(proc.toLatin1().data()));
}
bool QGLWidgetPrivate::renderCxPm(QPixmap*)
{
return false;
}
QT_END_NAMESPACE

View file

@ -1,69 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGL_EGL_P_H
#define QGL_EGL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of the QGLWidget class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <QtGui/qegl_p.h>
#include <QtGui/qeglcontext_p.h>
#include <QtGui/qeglproperties_p.h>
QT_BEGIN_NAMESPACE
class QGLFormat;
void qt_eglproperties_set_glformat(QEglProperties& props, const QGLFormat& format);
void qt_glformat_from_eglconfig(QGLFormat& format, const EGLConfig config);
QT_END_NAMESPACE
#endif // QGL_EGL_P_H

View file

@ -1,834 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGL_P_H
#define QGL_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of the QGLWidget class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include "QtOpenGL/qgl.h"
#include "QtOpenGL/qglcolormap.h"
#include "QtCore/qmap.h"
#include "QtCore/qthread.h"
#include "QtCore/qthreadstorage.h"
#include "QtCore/qhash.h"
#include "QtCore/qatomic.h"
#include "qwidget_p.h"
#include "qcache.h"
#include "qglpaintdevice_p.h"
#ifndef QT_NO_EGL
#include <QtGui/qegl_p.h>
#endif
QT_BEGIN_NAMESPACE
class QGLContext;
class QGLOverlayWidget;
class QPixmap;
class QPixmapFilter;
#ifndef QT_NO_EGL
class QEglContext;
#endif
QT_BEGIN_INCLUDE_NAMESPACE
#include <QtOpenGL/qglextensions_p.h>
QT_END_INCLUDE_NAMESPACE
class QGLFormatPrivate
{
public:
QGLFormatPrivate()
: ref(1)
{
opts = QGL::DoubleBuffer | QGL::DepthBuffer | QGL::Rgba | QGL::DirectRendering
| QGL::StencilBuffer | QGL::DeprecatedFunctions;
pln = 0;
depthSize = accumSize = stencilSize = redSize = greenSize = blueSize = alphaSize = -1;
numSamples = -1;
swapInterval = -1;
majorVersion = 1;
minorVersion = 0;
profile = QGLFormat::NoProfile;
}
QGLFormatPrivate(const QGLFormatPrivate *other)
: ref(1),
opts(other->opts),
pln(other->pln),
depthSize(other->depthSize),
accumSize(other->accumSize),
stencilSize(other->stencilSize),
redSize(other->redSize),
greenSize(other->greenSize),
blueSize(other->blueSize),
alphaSize(other->alphaSize),
numSamples(other->numSamples),
swapInterval(other->swapInterval),
majorVersion(other->majorVersion),
minorVersion(other->minorVersion),
profile(other->profile)
{
}
QAtomicInt ref;
QGL::FormatOptions opts;
int pln;
int depthSize;
int accumSize;
int stencilSize;
int redSize;
int greenSize;
int blueSize;
int alphaSize;
int numSamples;
int swapInterval;
int majorVersion;
int minorVersion;
QGLFormat::OpenGLContextProfile profile;
};
class QGLWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QGLWidget)
public:
QGLWidgetPrivate() : QWidgetPrivate()
, disable_clear_on_painter_begin(false)
#if defined(Q_WS_X11) && !defined(QT_NO_EGL)
, eglSurfaceWindowId(0)
#endif
{
isGLWidget = 1;
}
~QGLWidgetPrivate() {}
void init(QGLContext *context, const QGLWidget* shareWidget);
void initContext(QGLContext *context, const QGLWidget* shareWidget);
bool renderCxPm(QPixmap *pixmap);
void cleanupColormaps();
void aboutToDestroy() {
if (glcx)
glcx->reset();
}
QGLContext *glcx;
QGLWidgetGLPaintDevice glDevice;
bool autoSwap;
QGLColormap cmap;
#ifndef QT_OPENGL_ES
QMap<QString, int> displayListCache;
#endif
bool disable_clear_on_painter_begin;
#if defined(Q_WS_X11)
QGLOverlayWidget *olw;
#ifndef QT_NO_EGL
void recreateEglSurface();
WId eglSurfaceWindowId;
#endif
#endif
};
class QGLContextGroupResourceBase;
class QGLSharedResourceGuard;
// QGLContextPrivate has the responsibility of creating context groups.
// QGLContextPrivate maintains the reference counter and destroys
// context groups when needed.
class QGLContextGroup
{
public:
~QGLContextGroup();
QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;}
const QGLContext *context() const {return m_context;}
bool isSharing() const { return m_shares.size() >= 2; }
QList<const QGLContext *> shares() const { return m_shares; }
void addGuard(QGLSharedResourceGuard *guard);
void removeGuard(QGLSharedResourceGuard *guard);
static void addShare(const QGLContext *context, const QGLContext *share);
static void removeShare(const QGLContext *context);
private:
QGLContextGroup(const QGLContext *context);
QGLExtensionFuncs m_extensionFuncs;
const QGLContext *m_context; // context group's representative
QList<const QGLContext *> m_shares;
QHash<QGLContextGroupResourceBase *, void *> m_resources;
QGLSharedResourceGuard *m_guards; // double-linked list of active guards.
QAtomicInt m_refs;
void cleanupResources(const QGLContext *ctx);
friend class QGLContext;
friend class QGLContextPrivate;
friend class QGLContextGroupResourceBase;
};
// Get the context that resources for "ctx" will transfer to once
// "ctx" is destroyed. Returns null if nothing is sharing with ctx.
Q_OPENGL_EXPORT const QGLContext *qt_gl_transfer_context(const QGLContext *);
// GL extension definitions
class QGLExtensions {
public:
enum Extension {
TextureRectangle = 0x00000001,
SampleBuffers = 0x00000002,
GenerateMipmap = 0x00000004,
TextureCompression = 0x00000008,
FragmentProgram = 0x00000010,
MirroredRepeat = 0x00000020,
FramebufferObject = 0x00000040,
StencilTwoSide = 0x00000080,
StencilWrap = 0x00000100,
PackedDepthStencil = 0x00000200,
NVFloatBuffer = 0x00000400,
PixelBufferObject = 0x00000800,
FramebufferBlit = 0x00001000,
NPOTTextures = 0x00002000,
BGRATextureFormat = 0x00004000,
DDSTextureCompression = 0x00008000,
ETC1TextureCompression = 0x00010000,
PVRTCTextureCompression = 0x00020000,
FragmentShader = 0x00040000,
ElementIndexUint = 0x00080000,
Depth24 = 0x00100000,
SRGBFrameBuffer = 0x00200000
};
Q_DECLARE_FLAGS(Extensions, Extension)
static Extensions glExtensions();
static Extensions currentContextExtensions();
};
/*
QGLTemporaryContext - the main objective of this class is to have a way of
creating a GL context and making it current, without going via QGLWidget
and friends. At certain points during GL initialization we need a current
context in order decide what GL features are available, and to resolve GL
extensions. Having a light-weight way of creating such a context saves
initial application startup time, and it doesn't wind up creating recursive
conflicts.
The class currently uses a private d pointer to hide the platform specific
types. This could possibly been done inline with #ifdef'ery, but it causes
major headaches on e.g. X11 due to namespace pollution.
*/
class QGLTemporaryContextPrivate;
class QGLTemporaryContext {
public:
QGLTemporaryContext(bool directRendering = true, QWidget *parent = Q_NULLPTR);
~QGLTemporaryContext();
private:
QScopedPointer<QGLTemporaryContextPrivate> d;
};
class QGLTexture;
class QGLTextureDestroyer;
// This probably needs to grow to GL_MAX_VERTEX_ATTRIBS, but 3 is ok for now as that's
// all the GL2 engine uses:
#define QT_GL_VERTEX_ARRAY_TRACKED_COUNT 3
class QGLContextResourceBase;
class QGLContextPrivate
{
Q_DECLARE_PUBLIC(QGLContext)
public:
explicit QGLContextPrivate(QGLContext *context);
~QGLContextPrivate();
QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format,
QGLContext::BindOptions options);
QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key,
QGLContext::BindOptions options);
QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format,
QGLContext::BindOptions options);
QGLTexture *textureCacheLookup(const qint64 key, GLenum target);
void init(QPaintDevice *dev, const QGLFormat &format);
QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format);
int maxTextureSize();
void cleanup();
void setVertexAttribArrayEnabled(int arrayIndex, bool enabled = true);
void syncGlState(); // Makes sure the GL context's state is what we think it is
void swapRegion(const QRegion &region);
#ifndef QT_NO_EGL
QEglContext *eglContext;
EGLSurface eglSurface;
void destroyEglSurfaceForDevice();
EGLSurface eglSurfaceForDevice() const;
static QEglProperties *extraWindowSurfaceCreationProps;
static void setExtraWindowSurfaceCreationProps(QEglProperties *props);
#endif
#if defined(Q_WS_X11)
void* cx;
void* vi;
void* pbuf;
quint32 gpm;
int screen;
QHash<QPixmapData*, QPixmap> boundPixmaps;
QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key,
QGLContext::BindOptions options);
static void destroyGlSurfaceForPixmap(QPixmapData*);
static void unbindPixmapFromTexture(QPixmapData*);
#endif
QGLFormat glFormat;
QGLFormat reqFormat;
GLuint fbo;
uint valid : 1;
uint sharing : 1;
uint initDone : 1;
uint crWin : 1;
uint internal_context : 1;
uint version_flags_cached : 1;
uint extension_flags_cached : 1;
// workarounds for driver/hw bugs on different platforms
uint workaround_needsFullClearOnEveryFrame : 1;
uint workaround_brokenFBOReadBack : 1;
uint workaround_brokenTexSubImage : 1;
uint workaroundsCached : 1;
uint workaround_brokenTextureFromPixmap : 1;
uint workaround_brokenTextureFromPixmap_init : 1;
uint workaround_brokenScissor : 1;
uint workaround_brokenAlphaTexSubImage : 1;
uint workaround_brokenAlphaTexSubImage_init : 1;
#ifndef QT_NO_EGL
uint ownsEglContext : 1;
#endif
QPaintDevice *paintDevice;
QColor transpColor;
QGLContext *q_ptr;
QGLFormat::OpenGLVersionFlags version_flags;
QGLExtensions::Extensions extension_flags;
QGLContextGroup *group;
GLint max_texture_size;
GLuint current_fbo;
GLuint default_fbo;
QPaintEngine *active_engine;
QHash<QGLContextResourceBase *, void *> m_resources;
QGLTextureDestroyer *texture_destroyer;
bool vertexAttributeArraysEnabledState[QT_GL_VERTEX_ARRAY_TRACKED_COUNT];
static inline QGLContextGroup *contextGroup(const QGLContext *ctx) { return ctx->d_ptr->group; }
#if defined(Q_WS_X11)
static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs;
static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *);
#endif
static void setCurrentContext(QGLContext *context);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions)
// Temporarily make a context current if not already current or
// shared with the current contex. The previous context is made
// current when the object goes out of scope.
class Q_OPENGL_EXPORT QGLShareContextScope
{
public:
QGLShareContextScope(const QGLContext *ctx)
: m_oldContext(0)
{
QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
if (currentContext != ctx && !QGLContext::areSharing(ctx, currentContext)) {
m_oldContext = currentContext;
m_ctx = const_cast<QGLContext *>(ctx);
m_ctx->makeCurrent();
} else {
m_ctx = currentContext;
}
}
operator QGLContext *()
{
return m_ctx;
}
QGLContext *operator->()
{
return m_ctx;
}
~QGLShareContextScope()
{
if (m_oldContext)
m_oldContext->makeCurrent();
}
private:
QGLContext *m_oldContext;
QGLContext *m_ctx;
};
class QGLTextureDestroyer : public QObject
{
Q_OBJECT
public:
QGLTextureDestroyer() : QObject() {
qRegisterMetaType<GLuint>("GLuint");
connect(this, SIGNAL(freeTexture(QGLContext *, QPixmapData *, GLuint)),
this, SLOT(freeTexture_slot(QGLContext *, QPixmapData *, GLuint)));
}
void emitFreeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id) {
emit freeTexture(context, boundPixmap, id);
}
Q_SIGNALS:
void freeTexture(QGLContext *context, QPixmapData *boundPixmap, GLuint id);
private slots:
void freeTexture_slot(QGLContext *context, QPixmapData *boundPixmap, GLuint id) {
Q_UNUSED(boundPixmap);
#if defined(Q_WS_X11)
if (boundPixmap) {
QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext());
context->makeCurrent();
// Although glXReleaseTexImage is a glX call, it must be called while there
// is a current context - the context the pixmap was bound to a texture in.
// Otherwise the release doesn't do anything and you get BadDrawable errors
// when you come to delete the context.
QGLContextPrivate::unbindPixmapFromTexture(boundPixmap);
glDeleteTextures(1, &id);
if (oldContext)
oldContext->makeCurrent();
return;
}
#endif
QGLShareContextScope scope(context);
glDeleteTextures(1, &id);
}
};
// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
{
Q_OBJECT
public:
void emitAboutToDestroyContext(const QGLContext *context) {
emit aboutToDestroyContext(context);
}
static QGLSignalProxy *instance();
Q_SIGNALS:
void aboutToDestroyContext(const QGLContext *context);
};
class QGLTexture {
public:
QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D,
QGLContext::BindOptions opt = QGLContext::DefaultBindOption)
: context(ctx),
id(tx_id),
target(tx_target),
options(opt)
#if defined(Q_WS_X11)
, boundPixmap(0)
#endif
{}
~QGLTexture() {
if (options & QGLContext::MemoryManagedBindOption) {
Q_ASSERT(context);
#if !defined(Q_WS_X11)
QPixmapData *boundPixmap = 0;
#endif
context->d_ptr->texture_destroyer->emitFreeTexture(context, boundPixmap, id);
}
}
QGLContext *context;
GLuint id;
GLenum target;
QGLContext::BindOptions options;
#if defined(Q_WS_X11)
QPixmapData* boundPixmap;
#endif
bool canBindCompressedTexture
(const char *buf, int len, const char *format, bool *hasAlpha);
QSize bindCompressedTexture
(const QString& fileName, const char *format = 0);
QSize bindCompressedTexture
(const char *buf, int len, const char *format = 0);
QSize bindCompressedTextureDDS(const char *buf, int len);
QSize bindCompressedTexturePVR(const char *buf, int len);
};
struct QGLTextureCacheKey {
qint64 key;
QGLContextGroup *group;
};
inline bool operator==(const QGLTextureCacheKey &a, const QGLTextureCacheKey &b)
{
return a.key == b.key && a.group == b.group;
}
inline uint qHash(const QGLTextureCacheKey &key)
{
return qHash(key.key) ^ qHash(key.group);
}
class Q_AUTOTEST_EXPORT QGLTextureCache {
public:
QGLTextureCache();
~QGLTextureCache();
void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost);
void remove(qint64 key);
inline int size();
inline void setMaxCost(int newMax);
inline int maxCost();
inline QGLTexture* getTexture(QGLContext *ctx, qint64 key);
bool remove(QGLContext *ctx, GLuint textureId);
void removeContextTextures(QGLContext *ctx);
static QGLTextureCache *instance();
static void cleanupTexturesForCacheKey(qint64 cacheKey);
static void cleanupTexturesForPixampData(QPixmapData* pixmap);
static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
private:
QCache<QGLTextureCacheKey, QGLTexture> m_cache;
QReadWriteLock m_lock;
};
int QGLTextureCache::size() {
QReadLocker locker(&m_lock);
return m_cache.size();
}
void QGLTextureCache::setMaxCost(int newMax)
{
QWriteLocker locker(&m_lock);
m_cache.setMaxCost(newMax);
}
int QGLTextureCache::maxCost()
{
QReadLocker locker(&m_lock);
return m_cache.maxCost();
}
QGLTexture* QGLTextureCache::getTexture(QGLContext *ctx, qint64 key)
{
// Can't be a QReadLocker since QCache::object() modifies the cache (reprioritizes the object)
QWriteLocker locker(&m_lock);
const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
return m_cache.object(cacheKey);
}
extern Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine();
bool qt_gl_preferGL2Engine();
inline GLenum qt_gl_preferredTextureFormat()
{
return (QGLExtensions::glExtensions() & QGLExtensions::BGRATextureFormat) && QSysInfo::ByteOrder == QSysInfo::LittleEndian
? GL_BGRA : GL_RGBA;
}
inline GLenum qt_gl_preferredTextureTarget()
{
#if defined(QT_OPENGL_ES_2)
return GL_TEXTURE_2D;
#else
return (QGLExtensions::glExtensions() & QGLExtensions::TextureRectangle)
&& !qt_gl_preferGL2Engine()
? GL_TEXTURE_RECTANGLE_NV
: GL_TEXTURE_2D;
#endif
}
/*
Base for resources that are shared in a context group.
*/
class Q_OPENGL_EXPORT QGLContextGroupResourceBase
{
public:
QGLContextGroupResourceBase();
virtual ~QGLContextGroupResourceBase();
void insert(const QGLContext *context, void *value);
void *value(const QGLContext *context);
void cleanup(const QGLContext *context);
void cleanup(const QGLContext *context, void *value);
virtual void freeResource(void *value) = 0;
virtual void contextDeleted(const QGLContext *ctx);
protected:
QList<QGLContextGroup *> m_groups;
private:
QAtomicInt active;
};
/*
The QGLContextGroupResource template is used to manage a resource
for a group of sharing GL contexts. When the last context in the
group is destroyed, or when the QGLContextGroupResource object
itself is destroyed (implies potential context switches), the
resource will be freed.
The class used as the template class type needs to have a
constructor with the following signature:
T(const QGLContext *);
*/
template <class T>
class QGLContextGroupResource : public QGLContextGroupResourceBase
{
public:
~QGLContextGroupResource() {
for (int i = 0; i < m_groups.size(); ++i) {
const QGLContext *context = m_groups.at(i)->context();
T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context));
if (resource) {
QGLShareContextScope scope(context);
delete resource;
}
}
}
T *value(const QGLContext *context) {
T *resource = reinterpret_cast<T *>(QGLContextGroupResourceBase::value(context));
if (!resource) {
resource = new T(context);
insert(context, resource);
}
return resource;
}
protected:
void freeResource(void *resource) {
delete reinterpret_cast<T *>(resource);
}
};
/*
Base for resources that are context specific.
*/
class Q_OPENGL_EXPORT QGLContextResourceBase
{
public:
virtual ~QGLContextResourceBase() {
for (int i = 0; i < m_contexts.size(); ++i)
m_contexts.at(i)->d_ptr->m_resources.remove(this);
}
void insert(const QGLContext *context, void *value) {
context->d_ptr->m_resources.insert(this, value);
}
void *value(const QGLContext *context) {
return context->d_ptr->m_resources.value(this, 0);
}
virtual void freeResource(void *value) = 0;
protected:
QList<const QGLContext *> m_contexts;
};
/*
The QGLContextResource template is used to manage a resource for a
single GL context. Just before the context is destroyed (while it's
still the current context), or when the QGLContextResource object
itself is destroyed (implies potential context switches), the
resource will be freed. The class used as the template class type
needs to have a constructor with the following signature: T(const
QGLContext *);
*/
template <class T>
class QGLContextResource : public QGLContextResourceBase
{
public:
~QGLContextResource() {
for (int i = 0; i < m_contexts.size(); ++i) {
const QGLContext *context = m_contexts.at(i);
T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context));
if (resource) {
QGLShareContextScope scope(context);
delete resource;
}
}
}
T *value(const QGLContext *context) {
T *resource = reinterpret_cast<T *>(QGLContextResourceBase::value(context));
if (!resource) {
resource = new T(context);
insert(context, resource);
}
return resource;
}
protected:
void freeResource(void *resource) {
delete reinterpret_cast<T *>(resource);
}
};
// Put a guard around a GL object identifier and its context.
// When the context goes away, a shared context will be used
// in its place. If there are no more shared contexts, then
// the identifier is returned as zero - it is assumed that the
// context destruction cleaned up the identifier in this case.
class Q_OPENGL_EXPORT QGLSharedResourceGuard
{
public:
QGLSharedResourceGuard(const QGLContext *context)
: m_group(0), m_id(0), m_next(0), m_prev(0)
{
setContext(context);
}
QGLSharedResourceGuard(const QGLContext *context, GLuint id)
: m_group(0), m_id(id), m_next(0), m_prev(0)
{
setContext(context);
}
~QGLSharedResourceGuard();
const QGLContext *context() const
{
return m_group ? m_group->context() : 0;
}
void setContext(const QGLContext *context);
GLuint id() const
{
return m_id;
}
void setId(GLuint id)
{
m_id = id;
}
private:
QGLContextGroup *m_group;
GLuint m_id;
QGLSharedResourceGuard *m_next;
QGLSharedResourceGuard *m_prev;
friend class QGLContextGroup;
};
class QGLExtensionMatcher
{
public:
QGLExtensionMatcher(const char *str);
QGLExtensionMatcher();
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
template <class T>
class QGLEngineThreadStorage
{
public:
QPaintEngine *engine() {
QPaintEngine *&localEngine = storage.localData();
if (!localEngine)
localEngine = new T;
return localEngine;
}
private:
QThreadStorage<QPaintEngine *> storage;
};
QT_END_NAMESPACE
#endif // QGL_P_H

File diff suppressed because it is too large Load diff

View file

@ -1,563 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgl.h"
#include <qgl_p.h>
#include <qpixmap_x11_p.h>
#include <qpaintengine_opengl_p.h>
#include "qgl_egl_p.h"
#include "qcolormap.h"
#include <QDebug>
#include <QPixmap>
QT_BEGIN_NAMESPACE
/*
QGLTemporaryContext implementation
*/
class QGLTemporaryContextPrivate
{
public:
bool initialized;
Window window;
EGLContext context;
EGLSurface surface;
EGLDisplay display;
};
QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *)
: d(new QGLTemporaryContextPrivate)
{
d->initialized = false;
d->window = 0;
d->context = 0;
d->surface = 0;
int screen = 0;
d->display = QEgl::display();
EGLConfig config;
int numConfigs = 0;
EGLint attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
#ifdef QT_OPENGL_ES_2
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
#endif
EGL_NONE
};
eglChooseConfig(d->display, attribs, &config, 1, &numConfigs);
if (!numConfigs) {
qWarning("QGLTemporaryContext: No EGL configurations available.");
return;
}
XVisualInfo visualInfo;
XVisualInfo *vi;
int numVisuals;
visualInfo.visualid = QEgl::getCompatibleVisualId(config);
vi = XGetVisualInfo(X11->display, VisualIDMask, &visualInfo, &numVisuals);
if (!vi || numVisuals < 1) {
qWarning("QGLTemporaryContext: Unable to get X11 visual info id.");
return;
}
XSetWindowAttributes attr;
unsigned long mask;
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap(X11->display, DefaultRootWindow(X11->display), vi->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
d->window = XCreateWindow(X11->display, RootWindow(X11->display, screen),
0, 0, 1, 1, 0,
vi->depth, InputOutput, vi->visual,
mask, &attr);
d->surface = eglCreateWindowSurface(d->display, config, (EGLNativeWindowType) d->window, NULL);
if (d->surface == EGL_NO_SURFACE) {
qWarning("QGLTemporaryContext: Error creating EGL surface.");
XFree(vi);
XDestroyWindow(X11->display, d->window);
return;
}
EGLint contextAttribs[] = {
#ifdef QT_OPENGL_ES_2
EGL_CONTEXT_CLIENT_VERSION, 2,
#endif
EGL_NONE
};
d->context = eglCreateContext(d->display, config, 0, contextAttribs);
if (d->context != EGL_NO_CONTEXT
&& eglMakeCurrent(d->display, d->surface, d->surface, d->context))
{
d->initialized = true;
} else {
qWarning("QGLTemporaryContext: Error creating EGL context.");
eglDestroySurface(d->display, d->surface);
XDestroyWindow(X11->display, d->window);
}
XFree(vi);
}
QGLTemporaryContext::~QGLTemporaryContext()
{
if (d->initialized) {
eglMakeCurrent(d->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(d->display, d->context);
eglDestroySurface(d->display, d->surface);
XDestroyWindow(X11->display, d->window);
}
}
bool QGLFormat::hasOpenGLOverlays()
{
return false;
}
// Chooses the EGL config and creates the EGL context
bool QGLContext::chooseContext(const QGLContext* shareContext)
{
Q_D(QGLContext);
if (!device())
return false;
int devType = device()->devType();
QX11PixmapData *x11PixmapData = 0;
if (devType == QInternal::Pixmap) {
QPixmapData *pmd = static_cast<QPixmap*>(device())->data_ptr().data();
if (pmd->classId() == QPixmapData::X11Class)
x11PixmapData = static_cast<QX11PixmapData*>(pmd);
else {
// TODO: Replace the pixmap's data with a new QX11PixmapData
qWarning("WARNING: Creating a QGLContext on a QPixmap is only supported for X11 pixmap backend");
return false;
}
} else if ((devType != QInternal::Widget) && (devType != QInternal::Pbuffer)) {
qWarning("WARNING: Creating a QGLContext not supported on device type %d", devType);
return false;
}
// Only create the eglContext if we don't already have one:
if (d->eglContext == 0) {
d->eglContext = new QEglContext();
d->ownsEglContext = true;
d->eglContext->setApi(QEgl::OpenGL);
// If the device is a widget with WA_TranslucentBackground set, make sure the glFormat
// has the alpha channel option set:
if (devType == QInternal::Widget) {
QWidget* widget = static_cast<QWidget*>(device());
if (widget->testAttribute(Qt::WA_TranslucentBackground))
d->glFormat.setAlpha(true);
}
// Construct the configuration we need for this surface.
QEglProperties configProps;
configProps.setDeviceType(devType);
configProps.setRenderableType(QEgl::OpenGL);
qt_eglproperties_set_glformat(configProps, d->glFormat);
// Set buffer preserved for regular QWidgets, QGLWidgets are ok with either preserved or destroyed:
if ((devType == QInternal::Widget) && qobject_cast<QGLWidget*>(static_cast<QWidget*>(device())) == 0)
configProps.setValue(EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
if (!d->eglContext->chooseConfig(configProps, QEgl::BestPixelFormat)) {
delete d->eglContext;
d->eglContext = 0;
return false;
}
// Create a new context for the configuration.
QEglContext* eglSharedContext = shareContext ? shareContext->d_func()->eglContext : 0;
if (!d->eglContext->createContext(eglSharedContext)) {
delete d->eglContext;
d->eglContext = 0;
return false;
}
d->sharing = d->eglContext->isSharing();
if (d->sharing && shareContext)
const_cast<QGLContext *>(shareContext)->d_func()->sharing = true;
}
// Inform the higher layers about the actual format properties
qt_glformat_from_eglconfig(d->glFormat, d->eglContext->config());
// Do don't create the EGLSurface for everything.
// QWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
// QGLWidget - yes, create the EGLSurface and store it in QGLContextPrivate::eglSurface
// QPixmap - yes, create the EGLSurface but store it in QX11PixmapData::gl_surface
// QGLPixelBuffer - no, it creates the surface itself and stores it in QGLPixelBufferPrivate::pbuf
if (devType == QInternal::Widget) {
if (d->eglSurface != EGL_NO_SURFACE)
eglDestroySurface(d->eglContext->display(), d->eglSurface);
// extraWindowSurfaceCreationProps default to NULL unless were specifically set before
d->eglSurface = QEgl::createSurface(device(), d->eglContext->config(), d->extraWindowSurfaceCreationProps);
XFlush(X11->display);
setWindowCreated(true);
}
if (x11PixmapData) {
// TODO: Actually check to see if the existing surface can be re-used
if (x11PixmapData->gl_surface)
eglDestroySurface(d->eglContext->display(), (EGLSurface)x11PixmapData->gl_surface);
x11PixmapData->gl_surface = (void*)QEgl::createSurface(device(), d->eglContext->config());
}
return true;
}
void *QGLContext::chooseVisual()
{
qFatal("QGLContext::chooseVisual - this method must not be called as Qt is built with EGL support");
return 0;
}
void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
{
Q_UNUSED(f);
Q_UNUSED(bufDepth);
qFatal("QGLContext::tryVisual - this method must not be called as Qt is built with EGL support");
return 0;
}
void QGLWidget::resizeEvent(QResizeEvent *)
{
Q_D(QGLWidget);
if (!isValid())
return;
makeCurrent();
if (!d->glcx->initialized())
glInit();
resizeGL(width(), height());
//handle overlay
}
const QGLContext* QGLWidget::overlayContext() const
{
return 0;
}
void QGLWidget::makeOverlayCurrent()
{
//handle overlay
}
void QGLWidget::updateOverlayGL()
{
//handle overlay
}
void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext, bool deleteOldContext)
{
Q_D(QGLWidget);
if (context == 0) {
qWarning("QGLWidget::setContext: Cannot set null context");
return;
}
if (!context->deviceIsPixmap() && context->device() != this) {
qWarning("QGLWidget::setContext: Context must refer to this widget");
return;
}
if (d->glcx)
d->glcx->doneCurrent();
QGLContext* oldcx = d->glcx;
d->glcx = context;
bool createFailed = false;
if (!d->glcx->isValid()) {
// Create the QGLContext here, which in turn chooses the EGL config
// and creates the EGL context:
if (!d->glcx->create(shareContext ? shareContext : oldcx))
createFailed = true;
}
if (createFailed) {
if (deleteOldContext)
delete oldcx;
return;
}
d->eglSurfaceWindowId = winId(); // Remember the window id we created the surface for
}
void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget* shareWidget)
{
Q_Q(QGLWidget);
initContext(context, shareWidget);
if (q->isValid() && glcx->format().hasOverlay()) {
//no overlay
qWarning("QtOpenGL ES doesn't currently support overlays");
}
}
void QGLWidgetPrivate::cleanupColormaps()
{
}
const QGLColormap & QGLWidget::colormap() const
{
return d_func()->cmap;
}
void QGLWidget::setColormap(const QGLColormap &)
{
}
// Re-creates the EGL surface if the window ID has changed or if there isn't a surface
void QGLWidgetPrivate::recreateEglSurface()
{
Q_Q(QGLWidget);
Window currentId = q->winId();
// If the window ID has changed since the surface was created, we need to delete the
// old surface before re-creating a new one. Note: This should not be the case as the
// surface should be deleted before the old window id.
if (glcx->d_func()->eglSurface != EGL_NO_SURFACE && (currentId != eglSurfaceWindowId)) {
qWarning("EGL surface for deleted window %u was not destroyed", uint(eglSurfaceWindowId));
glcx->d_func()->destroyEglSurfaceForDevice();
}
if (glcx->d_func()->eglSurface == EGL_NO_SURFACE) {
glcx->d_func()->eglSurface = glcx->d_func()->eglContext->createSurface(q);
eglSurfaceWindowId = currentId;
}
}
QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key,
QGLContext::BindOptions options)
{
Q_Q(QGLContext);
// The EGL texture_from_pixmap has no facility to invert the y coordinate
if (!(options & QGLContext::CanFlipNativePixmapBindOption))
return 0;
static bool checkedForTFP = false;
static bool haveTFP = false;
static bool checkedForEglImageTFP = false;
static bool haveEglImageTFP = false;
if (!checkedForEglImageTFP) {
checkedForEglImageTFP = true;
// We need to be able to create an EGLImage from a native pixmap, which was split
// into a separate EGL extension, EGL_KHR_image_pixmap. It is possible to have
// eglCreateImageKHR & eglDestroyImageKHR without support for pixmaps, so we must
// check we have the EGLImage from pixmap functionality.
if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) {
// Being able to create an EGLImage from a native pixmap is also pretty useless
// without the ability to bind that EGLImage as a texture, which is provided by
// the GL_OES_EGL_image extension, which we try to resolve here:
haveEglImageTFP = qt_resolve_eglimage_gl_extensions(q);
if (haveEglImageTFP)
qDebug("Found EGL_KHR_image_pixmap & GL_OES_EGL_image extensions (preferred method)!");
}
}
if (!checkedForTFP) {
// Check for texture_from_pixmap egl extension
checkedForTFP = true;
if (QEgl::hasExtension("EGL_NOKIA_texture_from_pixmap") ||
QEgl::hasExtension("EGL_EXT_texture_from_pixmap"))
{
qDebug("Found texture_from_pixmap EGL extension!");
haveTFP = true;
}
}
if (!haveTFP && !haveEglImageTFP)
return 0;
QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pixmap->data_ptr().data());
Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class);
bool hasAlpha = pixmapData->hasAlphaChannel();
bool pixmapHasValidSurface = false;
bool textureIsBound = false;
GLuint textureId;
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
if (haveTFP && pixmapData->gl_surface &&
hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
{
pixmapHasValidSurface = true;
}
// If we already have a valid EGL surface for the pixmap, we should use it
if (pixmapHasValidSurface) {
EGLBoolean success;
success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
if (success == EGL_FALSE) {
qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
} else
textureIsBound = true;
}
// If the pixmap doesn't already have a valid surface, try binding it via EGLImage
// first, as going through EGLImage should be faster and better supported:
if (!textureIsBound && haveEglImageTFP) {
EGLImageKHR eglImage;
EGLint attribs[] = {
EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
EGL_NONE
};
eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
(EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs);
QGLContext* ctx = q;
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage);
GLint err = glGetError();
if (err == GL_NO_ERROR)
textureIsBound = true;
// Once the egl image is bound, the texture becomes a new sibling image and we can safely
// destroy the EGLImage we created for the pixmap:
if (eglImage != EGL_NO_IMAGE_KHR)
QEgl::eglDestroyImageKHR(QEgl::display(), eglImage);
}
if (!textureIsBound && haveTFP) {
// Check to see if the surface is still valid
if (pixmapData->gl_surface &&
hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha))
{
// Surface is invalid!
destroyGlSurfaceForPixmap(pixmapData);
}
if (pixmapData->gl_surface == 0) {
EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap,
QEgl::OpenGL,
hasAlpha ? QEgl::Translucent : QEgl::NoOptions);
pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config);
if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE)
return 0;
}
EGLBoolean success;
success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER);
if (success == EGL_FALSE) {
qWarning() << "eglBindTexImage() failed:" << QEgl::errorString();
eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
pixmapData->gl_surface = (void*)EGL_NO_SURFACE;
haveTFP = false; // If TFP isn't working, disable it's use
} else
textureIsBound = true;
}
QGLTexture *texture = 0;
if (textureIsBound) {
texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options);
pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture;
// We assume the cost of bound pixmaps is zero
QGLTextureCache::instance()->insert(q, key, texture, 0);
glBindTexture(GL_TEXTURE_2D, textureId);
} else
glDeleteTextures(1, &textureId);
return texture;
}
void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd)
{
Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
if (pixmapData->gl_surface) {
EGLBoolean success;
success = eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface);
if (success == EGL_FALSE) {
qWarning() << "destroyGlSurfaceForPixmap() - Error deleting surface: "
<< QEgl::errorString();
}
pixmapData->gl_surface = 0;
}
}
void QGLContextPrivate::unbindPixmapFromTexture(QPixmapData* pmd)
{
Q_ASSERT(pmd->classId() == QPixmapData::X11Class);
QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pmd);
if (pixmapData->gl_surface) {
EGLBoolean success;
success = eglReleaseTexImage(QEgl::display(),
(EGLSurface)pixmapData->gl_surface,
EGL_BACK_BUFFER);
if (success == EGL_FALSE) {
qWarning() << "unbindPixmapFromTexture() - Unable to release bound texture: "
<< QEgl::errorString();
}
}
}
QT_END_NAMESPACE

View file

@ -1,586 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtOpenGL/qgl.h>
#include <QtOpenGL/qgl_p.h>
#include <QtOpenGL/qglextensions_p.h>
#include <QtCore/qatomic.h>
#include "qglbuffer.h"
QT_BEGIN_NAMESPACE
/*!
\class QGLBuffer
\brief The QGLBuffer 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.
QGLBuffer objects can be copied around as a reference to the
underlying GL buffer object:
\code
QGLBuffer buffer1(QGLBuffer::IndexBuffer);
buffer1.create();
QGLBuffer buffer2 = buffer1;
\endcode
QGLBuffer performs a shallow copy when objects are copied in this
manner, but does not implement copy-on-write semantics. The original
object will be affected whenever the copy is modified.
*/
/*!
\enum QGLBuffer::Type
This enum defines the type of GL buffer object to create with QGLBuffer.
\value VertexBuffer Vertex buffer object for use when specifying
vertex arrays.
\value IndexBuffer Index buffer object for use with \c{glDrawElements()}.
\value PixelPackBuffer Pixel pack buffer object for reading pixel
data from the GL server (for example, with \c{glReadPixels()}).
Not supported under OpenGL/ES.
\value PixelUnpackBuffer Pixel unpack buffer object for writing pixel
data to the GL server (for example, with \c{glTexImage2D()}).
Not supported under OpenGL/ES.
*/
/*!
\enum QGLBuffer::UsagePattern
This enum defines the usage pattern of a QGLBuffer object.
\value StreamDraw The data will be set once and used a few times
for drawing operations. Under OpenGL/ES 1.1 this is identical
to StaticDraw.
\value StreamRead The data will be set once and used a few times
for reading data back from the GL server. Not supported
under OpenGL/ES.
\value StreamCopy The data will be set once and used a few times
for reading data back from the GL server for use in further
drawing operations. Not supported under OpenGL/ES.
\value StaticDraw The data will be set once and used many times
for drawing operations.
\value StaticRead The data will be set once and used many times
for reading data back from the GL server. Not supported
under OpenGL/ES.
\value StaticCopy The data will be set once and used many times
for reading data back from the GL server for use in further
drawing operations. Not supported under OpenGL/ES.
\value DynamicDraw The data will be modified repeatedly and used
many times for drawing operations.
\value DynamicRead The data will be modified repeatedly and used
many times for reading data back from the GL server.
Not supported under OpenGL/ES.
\value DynamicCopy The data will be modified repeatedly and used
many times for reading data back from the GL server for
use in further drawing operations. Not supported under OpenGL/ES.
*/
/*!
\enum QGLBuffer::Access
This enum defines the access mode for QGLBuffer::map().
\value ReadOnly The buffer will be mapped for reading only.
\value WriteOnly The buffer will be mapped for writing only.
\value ReadWrite The buffer will be mapped for reading and writing.
*/
class QGLBufferPrivate
{
public:
QGLBufferPrivate(QGLBuffer::Type t)
: ref(1),
type(t),
guard(0),
usagePattern(QGLBuffer::StaticDraw),
actualUsagePattern(QGLBuffer::StaticDraw)
{
}
QAtomicInt ref;
QGLBuffer::Type type;
QGLSharedResourceGuard guard;
QGLBuffer::UsagePattern usagePattern;
QGLBuffer::UsagePattern actualUsagePattern;
};
/*!
Constructs a new buffer object of type QGLBuffer::VertexBuffer.
Note: this constructor just creates the QGLBuffer instance. The actual
buffer object in the GL server is not created until create() is called.
\sa create()
*/
QGLBuffer::QGLBuffer()
: d_ptr(new QGLBufferPrivate(QGLBuffer::VertexBuffer))
{
}
/*!
Constructs a new buffer object of \a type.
Note: this constructor just creates the QGLBuffer instance. The actual
buffer object in the GL server is not created until create() is called.
\sa create()
*/
QGLBuffer::QGLBuffer(QGLBuffer::Type type)
: d_ptr(new QGLBufferPrivate(type))
{
}
/*!
Constructs a shallow copy of \a other.
Note: QGLBuffer does not implement copy-on-write semantics,
so \a other will be affected whenever the copy is modified.
*/
QGLBuffer::QGLBuffer(const QGLBuffer &other)
: d_ptr(other.d_ptr)
{
d_ptr->ref.ref();
}
#define ctx d->guard.context()
/*!
Destroys this buffer object, including the storage being
used in the GL server.
*/
QGLBuffer::~QGLBuffer()
{
if (!d_ptr->ref.deref()) {
destroy();
delete d_ptr;
}
}
/*!
Assigns a shallow copy of \a other to this object.
Note: QGLBuffer does not implement copy-on-write semantics,
so \a other will be affected whenever the copy is modified.
*/
QGLBuffer &QGLBuffer::operator=(const QGLBuffer &other)
{
if (d_ptr != other.d_ptr) {
other.d_ptr->ref.ref();
if (!d_ptr->ref.deref()) {
destroy();
delete d_ptr;
}
d_ptr = other.d_ptr;
}
return *this;
}
/*!
Returns the type of buffer represented by this object.
*/
QGLBuffer::Type QGLBuffer::type() const
{
Q_D(const QGLBuffer);
return d->type;
}
/*!
Returns the usage pattern for this buffer object.
The default value is StaticDraw.
\sa setUsagePattern()
*/
QGLBuffer::UsagePattern QGLBuffer::usagePattern() const
{
Q_D(const QGLBuffer);
return d->usagePattern;
}
/*!
Sets the usage pattern for this buffer object to \a value.
This function must be called before allocate() or write().
\sa usagePattern(), allocate(), write()
*/
void QGLBuffer::setUsagePattern(QGLBuffer::UsagePattern value)
{
Q_D(QGLBuffer);
#if defined(QT_OPENGL_ES_1)
// OpenGL/ES 1.1 does not support GL_STREAM_DRAW, so use GL_STATIC_DRAW.
// OpenGL/ES 2.0 does support GL_STREAM_DRAW.
d->usagePattern = value;
if (value == StreamDraw)
d->actualUsagePattern = StaticDraw;
else
d->actualUsagePattern = value;
#else
d->usagePattern = d->actualUsagePattern = value;
#endif
}
#undef ctx
/*!
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 QGLContext.
The buffer will be bound to and can only be used in
that context (or any other context that is shared with it).
This function will return false if the GL implementation
does not support buffers, or there is no current QGLContext.
\sa isCreated(), allocate(), write(), destroy()
*/
bool QGLBuffer::create()
{
Q_D(QGLBuffer);
if (d->guard.id())
return true;
const QGLContext *ctx = QGLContext::currentContext();
if (ctx) {
if (!qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
return false;
GLuint bufferId = 0;
glGenBuffers(1, &bufferId);
if (bufferId) {
d->guard.setContext(ctx);
d->guard.setId(bufferId);
return true;
}
}
return false;
}
#define ctx d->guard.context()
/*!
Returns true if this buffer has been created; false otherwise.
\sa create(), destroy()
*/
bool QGLBuffer::isCreated() const
{
Q_D(const QGLBuffer);
return d->guard.id() != 0;
}
/*!
Destroys this buffer object, including the storage being
used in the GL server. All references to the buffer will
become invalid.
*/
void QGLBuffer::destroy()
{
Q_D(QGLBuffer);
GLuint bufferId = d->guard.id();
if (bufferId) {
// Switch to the original creating context to destroy it.
QGLShareContextScope scope(d->guard.context());
glDeleteBuffers(1, &bufferId);
}
d->guard.setId(0);
d->guard.setContext(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 QGLBuffer::read(int offset, void *data, int count)
{
#if !defined(QT_OPENGL_ES)
Q_D(QGLBuffer);
if (!glGetBufferSubData || !d->guard.id())
return false;
while (glGetError() != GL_NO_ERROR) ; // Clear error state.
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 QGLBuffer::write(int offset, const void *data, int count)
{
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::allocate(): buffer not created");
#endif
Q_D(QGLBuffer);
if (d->guard.id())
glBufferSubData(d->type, offset, count, data);
}
/*!
Allocates \a count bytes of space to the buffer, initialized to
the contents of \a data. Any previous contents will be removed.
It is assumed that create() has been called on this buffer and that
it has been bound to the current context.
\sa create(), read(), write()
*/
void QGLBuffer::allocate(const void *data, int count)
{
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::allocate(): buffer not created");
#endif
Q_D(QGLBuffer);
if (d->guard.id())
glBufferData(d->type, count, data, d->actualUsagePattern);
}
/*!
\fn void QGLBuffer::allocate(int count)
\overload
Allocates \a count bytes of space to the buffer. Any previous
contents will be removed.
It is assumed that create() has been called on this buffer and that
it has been bound to the current context.
\sa create(), write()
*/
/*!
Binds the buffer associated with this object to the current
GL context. Returns false if binding was not possible, usually because
type() is not supported on this GL implementation.
The buffer must be bound to the same QGLContext current when create()
was called, or to another QGLContext that is sharing with it.
Otherwise, false will be returned from this function.
\sa release(), create()
*/
bool QGLBuffer::bind()
{
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::bind(): buffer not created");
#endif
Q_D(const QGLBuffer);
GLuint bufferId = d->guard.id();
if (bufferId) {
if (!QGLContext::areSharing(QGLContext::currentContext(),
d->guard.context())) {
#ifndef QT_NO_DEBUG
qWarning("QGLBuffer::bind: buffer is not valid in the current context");
#endif
return false;
}
glBindBuffer(d->type, bufferId);
return true;
} else {
return false;
}
}
/*!
Releases the buffer associated with this object from the
current GL context.
This function must be called with the same QGLContext current
as when bind() was called on the buffer.
\sa bind()
*/
void QGLBuffer::release()
{
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::release(): buffer not created");
#endif
Q_D(const QGLBuffer);
if (d->guard.id())
glBindBuffer(d->type, 0);
}
#undef ctx
/*!
Releases the buffer associated with \a type in the current
QGLContext.
This function is a direct call to \c{glBindBuffer(type, 0)}
for use when the caller does not know which QGLBuffer has
been bound to the context but wants to make sure that it
is released.
\code
QGLBuffer::release(QGLBuffer::VertexBuffer);
\endcode
*/
void QGLBuffer::release(QGLBuffer::Type type)
{
const QGLContext *ctx = QGLContext::currentContext();
if (ctx && qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx)))
glBindBuffer(GLenum(type), 0);
}
#define ctx d->guard.context()
/*!
Returns the GL identifier associated with this buffer; zero if
the buffer has not been created.
\sa isCreated()
*/
GLuint QGLBuffer::bufferId() const
{
Q_D(const QGLBuffer);
return d->guard.id();
}
#ifndef GL_BUFFER_SIZE
#define GL_BUFFER_SIZE 0x8764
#endif
/*!
Returns the size of the data in this buffer, for reading operations.
Returns -1 if fetching the buffer size is not supported, or the
buffer has not been created.
It is assumed that this buffer has been bound to the current context.
\sa isCreated(), bind()
*/
int QGLBuffer::size() const
{
Q_D(const QGLBuffer);
if (!d->guard.id())
return -1;
GLint value = -1;
glGetBufferParameteriv(d->type, GL_BUFFER_SIZE, &value);
return value;
}
/*!
Maps the contents of this buffer into the application's memory
space and returns a pointer to it. Returns null if memory
mapping is not possible. The \a access parameter indicates the
type of access to be performed.
It is assumed that create() has been called on this buffer and that
it has been bound to the current context.
This function is only supported under OpenGL/ES if the
\c{GL_OES_mapbuffer} extension is present.
\sa unmap(), create(), bind()
*/
void *QGLBuffer::map(QGLBuffer::Access access)
{
Q_D(QGLBuffer);
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::map(): buffer not created");
#endif
if (!d->guard.id())
return 0;
if (!glMapBufferARB)
return 0;
#ifdef QT_OPENGL_ES_2
if (access != QGLBuffer::WriteOnly)
return 0;
#endif
return glMapBufferARB(d->type, access);
}
/*!
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 QGLBuffer::unmap()
{
Q_D(QGLBuffer);
#ifndef QT_NO_DEBUG
if (!isCreated())
qWarning("QGLBuffer::unmap(): buffer not created");
#endif
if (!d->guard.id())
return false;
if (!glUnmapBufferARB)
return false;
return glUnmapBufferARB(d->type) == GL_TRUE;
}
QT_END_NAMESPACE

View file

@ -1,131 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLBUFFER_H
#define QGLBUFFER_H
#include <QtCore/qscopedpointer.h>
#include <QtOpenGL/qgl.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGLBufferPrivate;
class Q_OPENGL_EXPORT QGLBuffer
{
public:
enum Type
{
VertexBuffer = 0x8892, // GL_ARRAY_BUFFER
IndexBuffer = 0x8893, // GL_ELEMENT_ARRAY_BUFFER
PixelPackBuffer = 0x88EB, // GL_PIXEL_PACK_BUFFER
PixelUnpackBuffer = 0x88EC // GL_PIXEL_UNPACK_BUFFER
};
QGLBuffer();
explicit QGLBuffer(QGLBuffer::Type type);
QGLBuffer(const QGLBuffer &other);
~QGLBuffer();
QGLBuffer &operator=(const QGLBuffer &other);
enum UsagePattern
{
StreamDraw = 0x88E0, // GL_STREAM_DRAW
StreamRead = 0x88E1, // GL_STREAM_READ
StreamCopy = 0x88E2, // GL_STREAM_COPY
StaticDraw = 0x88E4, // GL_STATIC_DRAW
StaticRead = 0x88E5, // GL_STATIC_READ
StaticCopy = 0x88E6, // GL_STATIC_COPY
DynamicDraw = 0x88E8, // GL_DYNAMIC_DRAW
DynamicRead = 0x88E9, // GL_DYNAMIC_READ
DynamicCopy = 0x88EA // GL_DYNAMIC_COPY
};
enum Access
{
ReadOnly = 0x88B8, // GL_READ_ONLY
WriteOnly = 0x88B9, // GL_WRITE_ONLY
ReadWrite = 0x88BA // GL_READ_WRITE
};
QGLBuffer::Type type() const;
QGLBuffer::UsagePattern usagePattern() const;
void setUsagePattern(QGLBuffer::UsagePattern value);
bool create();
bool isCreated() const;
void destroy();
bool bind();
void release();
static void release(QGLBuffer::Type type);
GLuint bufferId() const;
int size() const;
bool read(int offset, void *data, int count);
void write(int offset, const void *data, int count);
void allocate(const void *data, int count);
inline void allocate(int count) { allocate(0, count); }
void *map(QGLBuffer::Access access);
bool unmap();
private:
QGLBufferPrivate *d_ptr;
Q_DECLARE_PRIVATE(QGLBuffer)
};
QT_END_NAMESPACE
QT_END_HEADER
#endif

View file

@ -1,301 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\class QGLColormap
\brief The QGLColormap class is used for installing custom colormaps into
a QGLWidget.
\module OpenGL
\ingroup painting-3D
\ingroup shared
QGLColormap provides a platform independent way of specifying and
installing indexed colormaps for a QGLWidget. QGLColormap is
especially useful when using the OpenGL color-index mode.
Under X11 you must use an X server that supports either a \c
PseudoColor or \c DirectColor visual class. If your X server
currently only provides a \c GrayScale, \c TrueColor, \c
StaticColor or \c StaticGray visual, you will not be able to
allocate colorcells for writing. If this is the case, try setting
your X server to 8 bit mode. It should then provide you with at
least a \c PseudoColor visual. Note that you may experience
colormap flashing if your X server is running in 8 bit mode.
The size() of the colormap is always set to 256
colors. Note that under Windows you can also install colormaps
in child widgets.
This class uses \l{implicit sharing} as a memory and speed
optimization.
Example of use:
\snippet doc/src/snippets/code/src_opengl_qglcolormap.cpp 0
\sa QGLWidget::setColormap(), QGLWidget::colormap()
*/
/*!
\fn Qt::HANDLE QGLColormap::handle()
\internal
Returns the handle for this color map.
*/
/*!
\fn void QGLColormap::setHandle(Qt::HANDLE handle)
\internal
Sets the handle for this color map to \a handle.
*/
#include "qglcolormap.h"
QT_BEGIN_NAMESPACE
QGLColormap::QGLColormapData QGLColormap::shared_null = { QAtomicInt(1), 0, 0 };
/*!
Construct a QGLColormap.
*/
QGLColormap::QGLColormap()
: d(&shared_null)
{
d->ref.ref();
}
/*!
Construct a shallow copy of \a map.
*/
QGLColormap::QGLColormap(const QGLColormap &map)
: d(map.d)
{
d->ref.ref();
}
/*!
Dereferences the QGLColormap and deletes it if this was the last
reference to it.
*/
QGLColormap::~QGLColormap()
{
if (!d->ref.deref())
cleanup(d);
}
void QGLColormap::cleanup(QGLColormap::QGLColormapData *x)
{
delete x->cells;
x->cells = 0;
delete x;
}
/*!
Assign a shallow copy of \a map to this QGLColormap.
*/
QGLColormap & QGLColormap::operator=(const QGLColormap &map)
{
map.d->ref.ref();
if (!d->ref.deref())
cleanup(d);
d = map.d;
return *this;
}
/*!
\fn void QGLColormap::detach()
\internal
Detaches this QGLColormap from the shared block.
*/
void QGLColormap::detach_helper()
{
QGLColormapData *x = new QGLColormapData;
x->ref = 1;
x->cmapHandle = 0;
x->cells = 0;
if (d->cells) {
x->cells = new QVector<QRgb>(256);
*x->cells = *d->cells;
}
if (!d->ref.deref())
cleanup(d);
d = x;
}
/*!
Set cell at index \a idx in the colormap to color \a color.
*/
void QGLColormap::setEntry(int idx, QRgb color)
{
detach();
if (!d->cells)
d->cells = new QVector<QRgb>(256);
d->cells->replace(idx, color);
}
/*!
Set an array of cells in this colormap. \a count is the number of
colors that should be set, \a colors is the array of colors, and
\a base is the starting index. The first element in \a colors
is set at \a base in the colormap.
*/
void QGLColormap::setEntries(int count, const QRgb *colors, int base)
{
detach();
if (!d->cells)
d->cells = new QVector<QRgb>(256);
Q_ASSERT_X(colors && base >= 0 && (base + count) <= d->cells->size(), "QGLColormap::setEntries",
"preconditions not met");
for (int i = 0; i < count; ++i)
setEntry(base + i, colors[i]);
}
/*!
Returns the QRgb value in the colorcell with index \a idx.
*/
QRgb QGLColormap::entryRgb(int idx) const
{
if (d == &shared_null || !d->cells)
return 0;
else
return d->cells->at(idx);
}
/*!
\overload
Set the cell with index \a idx in the colormap to color \a color.
*/
void QGLColormap::setEntry(int idx, const QColor &color)
{
setEntry(idx, color.rgb());
}
/*!
Returns the QRgb value in the colorcell with index \a idx.
*/
QColor QGLColormap::entryColor(int idx) const
{
if (d == &shared_null || !d->cells)
return QColor();
else
return QColor(d->cells->at(idx));
}
/*!
Returns true if the colormap is empty or it is not in use
by a QGLWidget; 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 QGLWidget is also considered empty.
Compare size() with zero to determine if the colormap is empty
regardless of whether it is in use by a QGLWidget or not.
\sa size()
*/
bool QGLColormap::isEmpty() const
{
return d == &shared_null || d->cells == 0 || d->cells->size() == 0 || d->cmapHandle == 0;
}
/*!
Returns the number of colorcells in the colormap.
*/
int QGLColormap::size() const
{
return d->cells ? d->cells->size() : 0;
}
/*!
Returns the index of the color \a color. If \a color is not in the
map, -1 is returned.
*/
int QGLColormap::find(QRgb color) const
{
if (d->cells)
return d->cells->indexOf(color);
return -1;
}
/*!
Returns the index of the color that is the closest match to color
\a color.
*/
int QGLColormap::findNearest(QRgb color) const
{
int idx = find(color);
if (idx >= 0)
return idx;
int mapSize = size();
int mindist = 200000;
int r = qRed(color);
int g = qGreen(color);
int b = qBlue(color);
int rx, gx, bx, dist;
for (int i = 0; i < mapSize; ++i) {
QRgb ci = d->cells->at(i);
rx = r - qRed(ci);
gx = g - qGreen(ci);
bx = b - qBlue(ci);
dist = rx * rx + gx * gx + bx * bx; // calculate distance
if (dist < mindist) { // minimal?
mindist = dist;
idx = i;
}
}
return idx;
}
QT_END_NAMESPACE

View file

@ -1,104 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLCOLORMAP_H
#define QGLCOLORMAP_H
#include <QtGui/qcolor.h>
#include <QtCore/qvector.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class Q_OPENGL_EXPORT QGLColormap
{
public:
QGLColormap();
QGLColormap(const QGLColormap &);
~QGLColormap();
QGLColormap &operator=(const QGLColormap &);
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 QGLColormapData {
QAtomicInt ref;
QVector<QRgb> *cells;
Qt::HANDLE cmapHandle;
};
QGLColormapData *d;
static struct QGLColormapData shared_null;
static void cleanup(QGLColormapData *x);
void detach_helper();
friend class QGLWidget;
friend class QGLWidgetPrivate;
};
inline void QGLColormap::detach()
{
if (d->ref != 1)
detach_helper();
}
QT_END_NAMESPACE
QT_END_HEADER
#endif // QGLCOLORMAP_H

View file

@ -1,439 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qgl_p.h"
#include <qglframebufferobject.h>
QT_BEGIN_NAMESPACE
static void *qt_gl_getProcAddress_search
(QGLContext *ctx, const char *name1, const char *name2,
const char *name3, const char *name4)
{
void *addr;
addr = ctx->getProcAddress(QLatin1String(name1));
if (addr)
return addr;
addr = ctx->getProcAddress(QLatin1String(name2));
if (addr)
return addr;
addr = ctx->getProcAddress(QLatin1String(name3));
if (addr)
return addr;
if (name4)
return ctx->getProcAddress(QLatin1String(name4));
return 0;
}
// Search for an extension function starting with the most likely
// function suffix first, and then trying the other variations.
#if defined(QT_OPENGL_ES)
#define qt_gl_getProcAddress(ctx,name) \
qt_gl_getProcAddress_search((ctx), name, name "OES", name "EXT", name "ARB")
#define qt_gl_getProcAddressEXT(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
#define qt_gl_getProcAddressARB(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "OES", name, name "ARB", name "EXT")
#define qt_gl_getProcAddressOES(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
#else
#define qt_gl_getProcAddress(ctx,name) \
qt_gl_getProcAddress_search((ctx), name, name "ARB", name "EXT", 0)
#define qt_gl_getProcAddressEXT(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "EXT", name, name "ARB", 0)
#define qt_gl_getProcAddressARB(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "ARB", name, name "EXT", 0)
#define qt_gl_getProcAddressOES(ctx,name) \
qt_gl_getProcAddress_search((ctx), name "OES", name, name "EXT", name "ARB")
#endif
bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
{
#if defined(QT_OPENGL_ES_2)
static bool have_resolved = false;
if (have_resolved)
return true;
have_resolved = true;
#else
if (glIsRenderbuffer != 0)
return true;
#endif
if (ctx == 0) {
qWarning("QGLFramebufferObject: Unable to resolve framebuffer object extensions -"
" make sure there is a current context when creating the framebuffer object.");
return false;
}
glBlitFramebufferEXT = (_glBlitFramebufferEXT) qt_gl_getProcAddressEXT(ctx, "glBlitFramebuffer");
glRenderbufferStorageMultisampleEXT =
(_glRenderbufferStorageMultisampleEXT) qt_gl_getProcAddressEXT(ctx, "glRenderbufferStorageMultisample");
#if !defined(QT_OPENGL_ES_2)
glIsRenderbuffer = (_glIsRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glIsRenderbuffer");
if (!glIsRenderbuffer)
return false; // Not much point searching for anything else.
glBindRenderbuffer = (_glBindRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glBindRenderbuffer");
glDeleteRenderbuffers = (_glDeleteRenderbuffers) qt_gl_getProcAddressEXT(ctx, "glDeleteRenderbuffers");
glGenRenderbuffers = (_glGenRenderbuffers) qt_gl_getProcAddressEXT(ctx, "glGenRenderbuffers");
glRenderbufferStorage = (_glRenderbufferStorage) qt_gl_getProcAddressEXT(ctx, "glRenderbufferStorage");
glGetRenderbufferParameteriv =
(_glGetRenderbufferParameteriv) qt_gl_getProcAddressEXT(ctx, "glGetRenderbufferParameteriv");
glIsFramebuffer = (_glIsFramebuffer) qt_gl_getProcAddressEXT(ctx, "glIsFramebuffer");
glBindFramebuffer = (_glBindFramebuffer) qt_gl_getProcAddressEXT(ctx, "glBindFramebuffer");
glDeleteFramebuffers = (_glDeleteFramebuffers) qt_gl_getProcAddressEXT(ctx, "glDeleteFramebuffers");
glGenFramebuffers = (_glGenFramebuffers) qt_gl_getProcAddressEXT(ctx, "glGenFramebuffers");
glCheckFramebufferStatus = (_glCheckFramebufferStatus) qt_gl_getProcAddressEXT(ctx, "glCheckFramebufferStatus");
glFramebufferTexture2D = (_glFramebufferTexture2D) qt_gl_getProcAddressEXT(ctx, "glFramebufferTexture2D");
glFramebufferRenderbuffer = (_glFramebufferRenderbuffer) qt_gl_getProcAddressEXT(ctx, "glFramebufferRenderbuffer");
glGetFramebufferAttachmentParameteriv =
(_glGetFramebufferAttachmentParameteriv) qt_gl_getProcAddressEXT(ctx, "glGetFramebufferAttachmentParameteriv");
glGenerateMipmap = (_glGenerateMipmap) qt_gl_getProcAddressEXT(ctx, "glGenerateMipmap");
return glIsRenderbuffer != 0;
#else
return true;
#endif
}
#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_version_1_3_functions(QGLContext *ctx)
{
if (glMultiTexCoord4f != 0)
return true;
QGLContext cx(QGLFormat::defaultFormat());
glMultiTexCoord4f = (_glMultiTexCoord4f) ctx->getProcAddress(QLatin1String("glMultiTexCoord4f"));
glActiveTexture = (_glActiveTexture) ctx->getProcAddress(QLatin1String("glActiveTexture"));
return glMultiTexCoord4f && glActiveTexture;
}
#endif
#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_stencil_face_extension(QGLContext *ctx)
{
if (glActiveStencilFaceEXT != 0)
return true;
QGLContext cx(QGLFormat::defaultFormat());
glActiveStencilFaceEXT = (_glActiveStencilFaceEXT) ctx->getProcAddress(QLatin1String("glActiveStencilFaceEXT"));
return glActiveStencilFaceEXT;
}
#endif
#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_frag_program_extensions(QGLContext *ctx)
{
if (glProgramStringARB != 0)
return true;
// ARB_fragment_program
glProgramStringARB = (_glProgramStringARB) ctx->getProcAddress(QLatin1String("glProgramStringARB"));
glBindProgramARB = (_glBindProgramARB) ctx->getProcAddress(QLatin1String("glBindProgramARB"));
glDeleteProgramsARB = (_glDeleteProgramsARB) ctx->getProcAddress(QLatin1String("glDeleteProgramsARB"));
glGenProgramsARB = (_glGenProgramsARB) ctx->getProcAddress(QLatin1String("glGenProgramsARB"));
glProgramLocalParameter4fvARB = (_glProgramLocalParameter4fvARB) ctx->getProcAddress(QLatin1String("glProgramLocalParameter4fvARB"));
return glProgramStringARB
&& glBindProgramARB
&& glDeleteProgramsARB
&& glGenProgramsARB
&& glProgramLocalParameter4fvARB;
}
#endif
bool qt_resolve_buffer_extensions(QGLContext *ctx)
{
if (!QGLContextPrivate::extensionFuncs(ctx).qt_bufferFuncsResolved) {
#if defined(QGL_RESOLVE_BUFFER_FUNCS)
glBindBuffer = (_glBindBuffer) qt_gl_getProcAddressARB(ctx, "glBindBuffer");
glDeleteBuffers = (_glDeleteBuffers) qt_gl_getProcAddressARB(ctx, "glDeleteBuffers");
glGenBuffers = (_glGenBuffers) qt_gl_getProcAddressARB(ctx, "glGenBuffers");
glBufferData = (_glBufferData) qt_gl_getProcAddressARB(ctx, "glBufferData");
glBufferSubData = (_glBufferSubData) qt_gl_getProcAddressARB(ctx, "glBufferSubData");
glGetBufferSubData = (_glGetBufferSubData) qt_gl_getProcAddressARB(ctx, "glGetBufferSubData");
glGetBufferParameteriv = (_glGetBufferParameteriv) qt_gl_getProcAddressARB(ctx, "glGetBufferParameteriv");
#endif
#ifdef QT_OPENGL_ES_2
QGLExtensionMatcher extensions;
if (extensions.match("GL_OES_mapbuffer")) {
glMapBufferARB = (_glMapBufferARB) qt_gl_getProcAddressARB(ctx, "glMapBufferOES");
glUnmapBufferARB = (_glUnmapBufferARB) qt_gl_getProcAddressARB(ctx, "glUnmapBufferOES");
}
#else
glMapBufferARB = (_glMapBufferARB) qt_gl_getProcAddressARB(ctx, "glMapBuffer");
glUnmapBufferARB = (_glUnmapBufferARB) qt_gl_getProcAddressARB(ctx, "glUnmapBuffer");
#endif
QGLContextPrivate::extensionFuncs(ctx).qt_bufferFuncsResolved = true;
}
#if defined(QGL_RESOLVE_BUFFER_FUNCS)
return glBindBuffer
&& glDeleteBuffers
&& glGenBuffers
&& glBufferData
&& glBufferSubData
&& glGetBufferParameteriv;
// glGetBufferSubData() is optional
#else
return true;
#endif
}
#ifndef QT_NO_EGL
bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx)
{
if (glEGLImageTargetTexture2DOES || glEGLImageTargetRenderbufferStorageOES)
return true;
glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetTexture2DOES"));
glEGLImageTargetRenderbufferStorageOES = (_glEGLImageTargetRenderbufferStorageOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetRenderbufferStorageOES"));
return glEGLImageTargetTexture2DOES && glEGLImageTargetRenderbufferStorageOES;
}
#endif
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
#if defined(QT_OPENGL_ES_2)
// The GLSL shader functions are always present in OpenGL/ES 2.0.
// The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
if (!QGLContextPrivate::extensionFuncs(ctx).qt_glslResolved) {
glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
QGLContextPrivate::extensionFuncs(ctx).qt_glslResolved = true;
}
return true;
#else
if (glCreateShader)
return true;
// Geometry shaders are optional...
glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT"));
glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT"));
glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
// Must at least have the FragmentShader extension to continue.
if (!(QGLExtensions::glExtensions() & QGLExtensions::FragmentShader))
return false;
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
if (glCreateShader) {
glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
} else {
// We may not have the standard shader functions, but we might
// have the older ARB functions instead.
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
glIsShader = 0;
glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
glIsProgram = 0;
glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
}
// Note: glShaderBinary(), glIsShader(), glIsProgram(), and
// glUniformMatrixNxMfv() are optional, but all other functions
// are required.
return glCreateShader &&
glShaderSource &&
glCompileShader &&
glDeleteProgram &&
glCreateProgram &&
glAttachShader &&
glDetachShader &&
glLinkProgram &&
glUseProgram &&
glDeleteProgram &&
glGetShaderInfoLog &&
glGetShaderiv &&
glGetShaderSource &&
glGetProgramiv &&
glGetProgramInfoLog &&
glGetUniformLocation &&
glUniform1fv &&
glUniform2fv &&
glUniform3fv &&
glUniform4fv &&
glUniform1i &&
glUniform1iv &&
glUniformMatrix2fv &&
glUniformMatrix3fv &&
glUniformMatrix4fv &&
glBindAttribLocation &&
glGetAttribLocation &&
glVertexAttrib1fv &&
glVertexAttrib2fv &&
glVertexAttrib3fv &&
glVertexAttrib4fv &&
glVertexAttribPointer &&
glDisableVertexAttribArray &&
glEnableVertexAttribArray;
#endif
}
#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_version_2_0_functions(QGLContext *ctx)
{
bool gl2supported = true;
if (!qt_resolve_glsl_extensions(ctx))
gl2supported = false;
if (!qt_resolve_version_1_3_functions(ctx))
gl2supported = false;
if (glStencilOpSeparate)
return gl2supported;
glBlendColor = (_glBlendColor) ctx->getProcAddress(QLatin1String("glBlendColor"));
glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate"));
if (!glBlendColor || !glStencilOpSeparate)
gl2supported = false;
return gl2supported;
}
#endif
QT_END_NAMESPACE

View file

@ -1,904 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGL_EXTENSIONS_P_H
#define QGL_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.
//
// extension prototypes
#ifndef APIENTRYP
# ifdef APIENTRY
# define APIENTRYP APIENTRY *
# else
# define APIENTRY
# define APIENTRYP *
# endif
#endif
#ifndef QT_NO_EGL
// Needed for EGLImageKHR definition:
#include <QtGui/qegl_p.h>
#endif
#include <QtCore/qglobal.h>
#ifndef GL_ARB_vertex_buffer_object
typedef ptrdiff_t GLintptrARB;
typedef ptrdiff_t GLsizeiptrARB;
#endif
#ifndef GL_VERSION_2_0
typedef char GLchar;
#endif
// ARB_vertex_buffer_object
typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint);
typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *);
typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *);
typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
typedef void (APIENTRY *_glBufferSubData) (GLenum, GLintptrARB, GLsizeiptrARB, const GLvoid *);
typedef void (APIENTRY *_glGetBufferSubData) (GLenum, GLintptrARB, GLsizeiptrARB, GLvoid *);
typedef void (APIENTRY *_glGetBufferParameteriv) (GLenum, GLenum, GLint *);
typedef GLvoid* (APIENTRY *_glMapBufferARB) (GLenum, GLenum);
typedef GLboolean (APIENTRY *_glUnmapBufferARB) (GLenum);
// We can call the buffer functions directly in OpenGL/ES 1.1 or higher,
// but all other platforms need to resolve the extensions.
#if defined(QT_OPENGL_ES)
#if defined(GL_OES_VERSION_1_0) && !defined(GL_OES_VERSION_1_1)
#define QGL_RESOLVE_BUFFER_FUNCS 1
#endif
#else
#define QGL_RESOLVE_BUFFER_FUNCS 1
#endif
// ARB_fragment_program
typedef void (APIENTRY *_glProgramStringARB) (GLenum, GLenum, GLsizei, const GLvoid *);
typedef void (APIENTRY *_glBindProgramARB) (GLenum, GLuint);
typedef void (APIENTRY *_glDeleteProgramsARB) (GLsizei, const GLuint *);
typedef void (APIENTRY *_glGenProgramsARB) (GLsizei, GLuint *);
typedef void (APIENTRY *_glProgramLocalParameter4fvARB) (GLenum, GLuint, const GLfloat *);
// GLSL
typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
typedef void (APIENTRY *_glCompileShader) (GLuint);
typedef void (APIENTRY *_glDeleteShader) (GLuint);
typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
typedef GLuint (APIENTRY *_glCreateProgram) ();
typedef void (APIENTRY *_glAttachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glDetachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glLinkProgram) (GLuint);
typedef void (APIENTRY *_glUseProgram) (GLuint);
typedef void (APIENTRY *_glDeleteProgram) (GLuint);
typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
typedef void (APIENTRY *_glMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
// Needed for GL2 engine:
typedef void (APIENTRY *_glStencilOpSeparate) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
typedef void (APIENTRY *_glActiveTexture) (GLenum);
typedef void (APIENTRY *_glBlendColor) (GLclampf, GLclampf, GLclampf, GLclampf);
// EXT_GL_framebuffer_object
typedef GLboolean (APIENTRY *_glIsRenderbuffer) (GLuint renderbuffer);
typedef void (APIENTRY *_glBindRenderbuffer) (GLenum target, GLuint renderbuffer);
typedef void (APIENTRY *_glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers);
typedef void (APIENTRY *_glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers);
typedef void (APIENTRY *_glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
typedef void (APIENTRY *_glGetRenderbufferParameteriv) (GLenum target, GLenum pname, GLint *params);
typedef GLboolean (APIENTRY *_glIsFramebuffer) (GLuint framebuffer);
typedef void (APIENTRY *_glBindFramebuffer) (GLenum target, GLuint framebuffer);
typedef void (APIENTRY *_glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers);
typedef void (APIENTRY *_glGenFramebuffers) (GLsizei n, GLuint *framebuffers);
typedef GLenum (APIENTRY *_glCheckFramebufferStatus) (GLenum target);
typedef void (APIENTRY *_glFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget,
GLuint texture, GLint level);
typedef void (APIENTRY *_glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
GLuint renderbuffer);
typedef void (APIENTRY *_glGetFramebufferAttachmentParameteriv) (GLenum target, GLenum attachment, GLenum pname,
GLint *params);
typedef void (APIENTRY *_glGenerateMipmap) (GLenum target);
// EXT_GL_framebuffer_blit
typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1, int srcY1,
int dstX0, int dstY0, int dstX1, int dstY1,
GLbitfield mask, GLenum filter);
// EXT_GL_framebuffer_multisample
typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height);
// GL_EXT_geometry_shader4
typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value);
typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment,
GLuint texture, GLint level);
typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLint layer);
typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment,
GLuint texture, GLint level, GLenum face);
// ARB_texture_compression
typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
GLsizei, GLint, GLsizei, const GLvoid *);
#ifndef QT_NO_EGL
// OES_EGL_image
// Note: We define these to take EGLImage whereas spec says they take a new GLeglImageOES
// type, which the EGL image should be cast to.
typedef void (APIENTRY *_glEGLImageTargetTexture2DOES) (GLenum, EGLImageKHR);
typedef void (APIENTRY *_glEGLImageTargetRenderbufferStorageOES) (GLenum, EGLImageKHR);
#endif
QT_BEGIN_NAMESPACE
struct QGLExtensionFuncs
{
QGLExtensionFuncs() {
#if !defined(QT_OPENGL_ES_2)
qt_glProgramStringARB = 0;
qt_glBindProgramARB = 0;
qt_glDeleteProgramsARB = 0;
qt_glGenProgramsARB = 0;
qt_glProgramLocalParameter4fvARB = 0;
// GLSL
qt_glCreateShader = 0;
qt_glShaderSource = 0;
qt_glShaderBinary = 0;
qt_glCompileShader = 0;
qt_glDeleteShader = 0;
qt_glIsShader = 0;
qt_glCreateProgram = 0;
qt_glAttachShader = 0;
qt_glDetachShader = 0;
qt_glLinkProgram = 0;
qt_glUseProgram = 0;
qt_glDeleteProgram = 0;
qt_glIsProgram = 0;
qt_glGetShaderInfoLog = 0;
qt_glGetShaderiv = 0;
qt_glGetShaderSource = 0;
qt_glGetProgramiv = 0;
qt_glGetProgramInfoLog = 0;
qt_glGetUniformLocation = 0;
qt_glUniform4fv = 0;
qt_glUniform3fv = 0;
qt_glUniform2fv = 0;
qt_glUniform1fv = 0;
qt_glUniform1i = 0;
qt_glUniform1iv = 0;
qt_glUniformMatrix2fv = 0;
qt_glUniformMatrix3fv = 0;
qt_glUniformMatrix4fv = 0;
qt_glUniformMatrix2x3fv = 0;
qt_glUniformMatrix2x4fv = 0;
qt_glUniformMatrix3x2fv = 0;
qt_glUniformMatrix3x4fv = 0;
qt_glUniformMatrix4x2fv = 0;
qt_glUniformMatrix4x3fv = 0;
qt_glBindAttribLocation = 0;
qt_glGetAttribLocation = 0;
qt_glVertexAttrib1fv = 0;
qt_glVertexAttrib2fv = 0;
qt_glVertexAttrib3fv = 0;
qt_glVertexAttrib4fv = 0;
qt_glVertexAttribPointer = 0;
qt_glDisableVertexAttribArray = 0;
qt_glEnableVertexAttribArray = 0;
// Extras for GL2 engine:
qt_glActiveTexture = 0;
qt_glStencilOpSeparate = 0;
qt_glBlendColor = 0;
qt_glActiveStencilFaceEXT = 0;
qt_glMultiTexCoord4f = 0;
#else
qt_glslResolved = false;
qt_glGetProgramBinaryOES = 0;
qt_glProgramBinaryOES = 0;
#endif
// FBOs
#if !defined(QT_OPENGL_ES_2)
qt_glIsRenderbuffer = 0;
qt_glBindRenderbuffer = 0;
qt_glDeleteRenderbuffers = 0;
qt_glGenRenderbuffers = 0;
qt_glRenderbufferStorage = 0;
qt_glGetRenderbufferParameteriv = 0;
qt_glIsFramebuffer = 0;
qt_glBindFramebuffer = 0;
qt_glDeleteFramebuffers = 0;
qt_glGenFramebuffers = 0;
qt_glCheckFramebufferStatus = 0;
qt_glFramebufferTexture2D = 0;
qt_glFramebufferRenderbuffer = 0;
qt_glGetFramebufferAttachmentParameteriv = 0;
qt_glGenerateMipmap = 0;
#endif
qt_glBlitFramebufferEXT = 0;
qt_glRenderbufferStorageMultisampleEXT = 0;
// Buffer objects:
#if defined(QGL_RESOLVE_BUFFER_FUNCS)
qt_glBindBuffer = 0;
qt_glDeleteBuffers = 0;
qt_glGenBuffers = 0;
qt_glBufferData = 0;
qt_glBufferSubData = 0;
qt_glGetBufferSubData = 0;
qt_glGetBufferParameteriv = 0;
#endif
qt_glMapBufferARB = 0;
qt_glUnmapBufferARB = 0;
qt_bufferFuncsResolved = false;
qt_glProgramParameteriEXT = 0;
qt_glFramebufferTextureEXT = 0;
qt_glFramebufferTextureLayerEXT = 0;
qt_glFramebufferTextureFaceEXT = 0;
#if !defined(QT_OPENGL_ES)
// Texture compression
qt_glCompressedTexImage2DARB = 0;
#endif
#ifndef QT_NO_EGL
// OES_EGL_image
qt_glEGLImageTargetTexture2DOES = 0;
qt_glEGLImageTargetRenderbufferStorageOES = 0;
#endif
}
#if !defined(QT_OPENGL_ES_2)
_glProgramStringARB qt_glProgramStringARB;
_glBindProgramARB qt_glBindProgramARB;
_glDeleteProgramsARB qt_glDeleteProgramsARB;
_glGenProgramsARB qt_glGenProgramsARB;
_glProgramLocalParameter4fvARB qt_glProgramLocalParameter4fvARB;
// GLSL definitions
_glCreateShader qt_glCreateShader;
_glShaderSource qt_glShaderSource;
_glShaderBinary qt_glShaderBinary;
_glCompileShader qt_glCompileShader;
_glDeleteShader qt_glDeleteShader;
_glIsShader qt_glIsShader;
_glCreateProgram qt_glCreateProgram;
_glAttachShader qt_glAttachShader;
_glDetachShader qt_glDetachShader;
_glLinkProgram qt_glLinkProgram;
_glUseProgram qt_glUseProgram;
_glDeleteProgram qt_glDeleteProgram;
_glIsProgram qt_glIsProgram;
_glGetShaderInfoLog qt_glGetShaderInfoLog;
_glGetShaderiv qt_glGetShaderiv;
_glGetShaderSource qt_glGetShaderSource;
_glGetProgramiv qt_glGetProgramiv;
_glGetProgramInfoLog qt_glGetProgramInfoLog;
_glGetUniformLocation qt_glGetUniformLocation;
_glUniform4fv qt_glUniform4fv;
_glUniform3fv qt_glUniform3fv;
_glUniform2fv qt_glUniform2fv;
_glUniform1fv qt_glUniform1fv;
_glUniform1i qt_glUniform1i;
_glUniform1iv qt_glUniform1iv;
_glUniformMatrix2fv qt_glUniformMatrix2fv;
_glUniformMatrix3fv qt_glUniformMatrix3fv;
_glUniformMatrix4fv qt_glUniformMatrix4fv;
_glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
_glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
_glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
_glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
_glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
_glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
_glBindAttribLocation qt_glBindAttribLocation;
_glGetAttribLocation qt_glGetAttribLocation;
_glVertexAttrib1fv qt_glVertexAttrib1fv;
_glVertexAttrib2fv qt_glVertexAttrib2fv;
_glVertexAttrib3fv qt_glVertexAttrib3fv;
_glVertexAttrib4fv qt_glVertexAttrib4fv;
_glVertexAttribPointer qt_glVertexAttribPointer;
_glDisableVertexAttribArray qt_glDisableVertexAttribArray;
_glEnableVertexAttribArray qt_glEnableVertexAttribArray;
#else
bool qt_glslResolved;
_glGetProgramBinaryOES qt_glGetProgramBinaryOES;
_glProgramBinaryOES qt_glProgramBinaryOES;
#endif
_glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
_glMultiTexCoord4f qt_glMultiTexCoord4f;
#if !defined(QT_OPENGL_ES_2)
// Extras needed for GL2 engine:
_glActiveTexture qt_glActiveTexture;
_glStencilOpSeparate qt_glStencilOpSeparate;
_glBlendColor qt_glBlendColor;
#endif
// FBOs
#if !defined(QT_OPENGL_ES_2)
_glIsRenderbuffer qt_glIsRenderbuffer;
_glBindRenderbuffer qt_glBindRenderbuffer;
_glDeleteRenderbuffers qt_glDeleteRenderbuffers;
_glGenRenderbuffers qt_glGenRenderbuffers;
_glRenderbufferStorage qt_glRenderbufferStorage;
_glGetRenderbufferParameteriv qt_glGetRenderbufferParameteriv;
_glIsFramebuffer qt_glIsFramebuffer;
_glBindFramebuffer qt_glBindFramebuffer;
_glDeleteFramebuffers qt_glDeleteFramebuffers;
_glGenFramebuffers qt_glGenFramebuffers;
_glCheckFramebufferStatus qt_glCheckFramebufferStatus;
_glFramebufferTexture2D qt_glFramebufferTexture2D;
_glFramebufferRenderbuffer qt_glFramebufferRenderbuffer;
_glGetFramebufferAttachmentParameteriv qt_glGetFramebufferAttachmentParameteriv;
_glGenerateMipmap qt_glGenerateMipmap;
#endif
_glBlitFramebufferEXT qt_glBlitFramebufferEXT;
_glRenderbufferStorageMultisampleEXT qt_glRenderbufferStorageMultisampleEXT;
// Buffer objects
#if defined(QGL_RESOLVE_BUFFER_FUNCS)
_glBindBuffer qt_glBindBuffer;
_glDeleteBuffers qt_glDeleteBuffers;
_glGenBuffers qt_glGenBuffers;
_glBufferData qt_glBufferData;
_glBufferSubData qt_glBufferSubData;
_glGetBufferSubData qt_glGetBufferSubData;
_glGetBufferParameteriv qt_glGetBufferParameteriv;
#endif
_glMapBufferARB qt_glMapBufferARB;
_glUnmapBufferARB qt_glUnmapBufferARB;
bool qt_bufferFuncsResolved;
// Geometry shaders...
_glProgramParameteriEXT qt_glProgramParameteriEXT;
_glFramebufferTextureEXT qt_glFramebufferTextureEXT;
_glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT;
_glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT;
#if !defined(QT_OPENGL_ES)
// Texture compression
_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
#endif
#ifndef QT_NO_EGL
// OES_EGL_image
_glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES;
_glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES;
#endif
};
// OpenGL constants
#ifndef FRAMEBUFFER_SRGB_CAPABLE_EXT
#define FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA
#endif
#ifndef FRAMEBUFFER_SRGB_EXT
#define FRAMEBUFFER_SRGB_EXT 0x8DB9
#endif
#ifndef GL_ARRAY_BUFFER
#define GL_ARRAY_BUFFER 0x8892
#endif
#ifndef GL_STATIC_DRAW
#define GL_STATIC_DRAW 0x88E4
#endif
/* NV_texture_rectangle */
#ifndef GL_NV_texture_rectangle
#define GL_TEXTURE_RECTANGLE_NV 0x84F5
#define GL_TEXTURE_BINDING_RECTANGLE_NV 0x84F6
#define GL_PROXY_TEXTURE_RECTANGLE_NV 0x84F7
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 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_IBM_texture_mirrored_repeat
#define GL_MIRRORED_REPEAT_IBM 0x8370
#endif
#ifndef GL_SGIS_generate_mipmap
#define GL_GENERATE_MIPMAP_SGIS 0x8191
#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
#endif
// ARB_fragment_program extension protos
#ifndef GL_FRAGMENT_PROGRAM_ARB
#define GL_FRAGMENT_PROGRAM_ARB 0x8804
#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
#endif
#ifndef GL_PIXEL_UNPACK_BUFFER_ARB
#define GL_PIXEL_UNPACK_BUFFER_ARB 0x88EC
#endif
#ifndef GL_WRITE_ONLY_ARB
#define GL_WRITE_ONLY_ARB 0x88B9
#endif
#ifndef GL_STREAM_DRAW_ARB
#define GL_STREAM_DRAW_ARB 0x88E0
#endif
// Stencil wrap and two-side defines
#ifndef GL_STENCIL_TEST_TWO_SIDE_EXT
#define GL_STENCIL_TEST_TWO_SIDE_EXT 0x8910
#endif
#ifndef GL_INCR_WRAP_EXT
#define GL_INCR_WRAP_EXT 0x8507
#endif
#ifndef GL_DECR_WRAP_EXT
#define GL_DECR_WRAP_EXT 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_OES
#define GL_DEPTH_COMPONENT24_OES 0x81A6
#endif
#ifndef GL_EXT_framebuffer_object
#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
#define GL_FRAMEBUFFER_EXT 0x8D40
#define GL_RENDERBUFFER_EXT 0x8D41
#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
#define GL_STENCIL_INDEX_EXT 0x8D45
#define GL_STENCIL_INDEX1_EXT 0x8D46
#define GL_STENCIL_INDEX4_EXT 0x8D47
#define GL_STENCIL_INDEX8_EXT 0x8D48
#define GL_STENCIL_INDEX16_EXT 0x8D49
#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
#endif
// GL_EXT_framebuffer_blit
#ifndef GL_READ_FRAMEBUFFER_EXT
#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
#endif
// GL_EXT_framebuffer_multisample
#ifndef GL_RENDERBUFFER_SAMPLES_EXT
#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
#endif
#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
#endif
#ifndef GL_MAX_SAMPLES_EXT
#define GL_MAX_SAMPLES_EXT 0x8D57
#endif
#ifndef GL_DRAW_FRAMEBUFFER_EXT
#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
#endif
#ifndef GL_EXT_packed_depth_stencil
#define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
#define GL_DEPTH24_STENCIL8_EXT 0x88F0
#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
#endif
// ### hm. should be part of the GL 1.2 spec..
#ifndef GL_CLAMP_TO_EDGE
#define GL_CLAMP_TO_EDGE 0x812F
#endif
#ifndef GL_VERSION_1_2
#define GL_PACK_SKIP_IMAGES 0x806B
#define GL_PACK_IMAGE_HEIGHT 0x806C
#define GL_UNPACK_SKIP_IMAGES 0x806D
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
#endif
#ifndef GL_VERSION_1_4
#define GL_CONSTANT_COLOR 0x8001
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
#define GL_CONSTANT_ALPHA 0x8003
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
#define GL_INCR_WRAP 0x8507
#define GL_DECR_WRAP 0x8508
#endif
#ifndef GL_VERSION_1_5
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_STREAM_DRAW 0x88E0
#define GL_STREAM_READ 0x88E1
#define GL_STREAM_COPY 0x88E2
#define GL_STATIC_DRAW 0x88E4
#define GL_STATIC_READ 0x88E5
#define GL_STATIC_COPY 0x88E6
#define GL_DYNAMIC_DRAW 0x88E8
#define GL_DYNAMIC_READ 0x88E9
#define GL_DYNAMIC_COPY 0x88EA
#endif
#ifndef GL_VERSION_2_0
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_FLOAT_VEC2 0x8B50
#define GL_FLOAT_VEC3 0x8B51
#define GL_FLOAT_VEC4 0x8B52
#define GL_INT_VEC2 0x8B53
#define GL_INT_VEC3 0x8B54
#define GL_INT_VEC4 0x8B55
#define GL_BOOL 0x8B56
#define GL_BOOL_VEC2 0x8B57
#define GL_BOOL_VEC3 0x8B58
#define GL_BOOL_VEC4 0x8B59
#define GL_FLOAT_MAT2 0x8B5A
#define GL_FLOAT_MAT3 0x8B5B
#define GL_FLOAT_MAT4 0x8B5C
#define GL_SAMPLER_1D 0x8B5D
#define GL_SAMPLER_2D 0x8B5E
#define GL_SAMPLER_3D 0x8B5F
#define GL_SAMPLER_CUBE 0x8B60
#define GL_COMPILE_STATUS 0x8B81
#define GL_LINK_STATUS 0x8B82
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_ACTIVE_UNIFORMS 0x8B86
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
#define GL_ACTIVE_ATTRIBUTES 0x8B89
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#endif
// Geometry shader defines
#ifndef GL_GEOMETRY_SHADER_EXT
# define GL_GEOMETRY_SHADER_EXT 0x8DD9
# define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
# define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
# define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
# define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
# define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
# define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
# define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
# define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
# define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
# define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
# define GL_LINES_ADJACENCY_EXT 0xA
# define GL_LINE_STRIP_ADJACENCY_EXT 0xB
# define GL_TRIANGLES_ADJACENCY_EXT 0xC
# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
# define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
# define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
# define GL_PROGRAM_POINT_SIZE_EXT 0x8642
#endif
#if !defined(QT_OPENGL_ES_2)
#define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB
#define glBindProgramARB QGLContextPrivate::extensionFuncs(ctx).qt_glBindProgramARB
#define glDeleteProgramsARB QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteProgramsARB
#define glGenProgramsARB QGLContextPrivate::extensionFuncs(ctx).qt_glGenProgramsARB
#define glProgramLocalParameter4fvARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramLocalParameter4fvARB
#define glActiveStencilFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glActiveStencilFaceEXT
#define glMultiTexCoord4f QGLContextPrivate::extensionFuncs(ctx).qt_glMultiTexCoord4f
#define glActiveTexture QGLContextPrivate::extensionFuncs(ctx).qt_glActiveTexture
#endif // !defined(QT_OPENGL_ES_2)
// FBOs
#if !defined(QT_OPENGL_ES_2)
#define glIsRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glIsRenderbuffer
#define glBindRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindRenderbuffer
#define glDeleteRenderbuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteRenderbuffers
#define glGenRenderbuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenRenderbuffers
#define glRenderbufferStorage QGLContextPrivate::extensionFuncs(ctx).qt_glRenderbufferStorage
#define glGetRenderbufferParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetRenderbufferParameteriv
#define glIsFramebuffer QGLContextPrivate::extensionFuncs(ctx).qt_glIsFramebuffer
#define glBindFramebuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindFramebuffer
#define glDeleteFramebuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteFramebuffers
#define glGenFramebuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenFramebuffers
#define glCheckFramebufferStatus QGLContextPrivate::extensionFuncs(ctx).qt_glCheckFramebufferStatus
#define glFramebufferTexture2D QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTexture2D
#define glFramebufferRenderbuffer QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferRenderbuffer
#define glGetFramebufferAttachmentParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetFramebufferAttachmentParameteriv
#define glGenerateMipmap QGLContextPrivate::extensionFuncs(ctx).qt_glGenerateMipmap
#endif // QT_OPENGL_ES_2
#define glBlitFramebufferEXT QGLContextPrivate::extensionFuncs(ctx).qt_glBlitFramebufferEXT
#define glRenderbufferStorageMultisampleEXT QGLContextPrivate::extensionFuncs(ctx).qt_glRenderbufferStorageMultisampleEXT
// Buffer objects
#if defined(QGL_RESOLVE_BUFFER_FUNCS)
#define glBindBuffer QGLContextPrivate::extensionFuncs(ctx).qt_glBindBuffer
#define glDeleteBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteBuffers
#define glGenBuffers QGLContextPrivate::extensionFuncs(ctx).qt_glGenBuffers
#define glBufferData QGLContextPrivate::extensionFuncs(ctx).qt_glBufferData
#define glBufferSubData QGLContextPrivate::extensionFuncs(ctx).qt_glBufferSubData
#define glGetBufferSubData QGLContextPrivate::extensionFuncs(ctx).qt_glGetBufferSubData
#define glGetBufferParameteriv QGLContextPrivate::extensionFuncs(ctx).qt_glGetBufferParameteriv
#endif
#define glMapBufferARB QGLContextPrivate::extensionFuncs(ctx).qt_glMapBufferARB
#define glUnmapBufferARB QGLContextPrivate::extensionFuncs(ctx).qt_glUnmapBufferARB
// GLSL
#if !defined(QT_OPENGL_ES_2)
#define glCreateShader QGLContextPrivate::extensionFuncs(ctx).qt_glCreateShader
#define glShaderSource QGLContextPrivate::extensionFuncs(ctx).qt_glShaderSource
#define glShaderBinary QGLContextPrivate::extensionFuncs(ctx).qt_glShaderBinary
#define glCompileShader QGLContextPrivate::extensionFuncs(ctx).qt_glCompileShader
#define glDeleteShader QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteShader
#define glIsShader QGLContextPrivate::extensionFuncs(ctx).qt_glIsShader
#define glCreateProgram QGLContextPrivate::extensionFuncs(ctx).qt_glCreateProgram
#define glAttachShader QGLContextPrivate::extensionFuncs(ctx).qt_glAttachShader
#define glDetachShader QGLContextPrivate::extensionFuncs(ctx).qt_glDetachShader
#define glLinkProgram QGLContextPrivate::extensionFuncs(ctx).qt_glLinkProgram
#define glUseProgram QGLContextPrivate::extensionFuncs(ctx).qt_glUseProgram
#define glDeleteProgram QGLContextPrivate::extensionFuncs(ctx).qt_glDeleteProgram
#define glIsProgram QGLContextPrivate::extensionFuncs(ctx).qt_glIsProgram
#define glGetShaderInfoLog QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderInfoLog
#define glGetShaderiv QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderiv
#define glGetShaderSource QGLContextPrivate::extensionFuncs(ctx).qt_glGetShaderSource
#define glGetProgramiv QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramiv
#define glGetProgramInfoLog QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramInfoLog
#define glGetUniformLocation QGLContextPrivate::extensionFuncs(ctx).qt_glGetUniformLocation
#define glUniform4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform4fv
#define glUniform3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform3fv
#define glUniform2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform2fv
#define glUniform1fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1i
#define glUniform1iv QGLContextPrivate::extensionFuncs(ctx).qt_glUniform1iv
#define glUniformMatrix2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2fv
#define glUniformMatrix3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3fv
#define glUniformMatrix4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4fv
#define glUniformMatrix2x3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2x3fv
#define glUniformMatrix2x4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix2x4fv
#define glUniformMatrix3x2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3x2fv
#define glUniformMatrix3x4fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix3x4fv
#define glUniformMatrix4x2fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4x2fv
#define glUniformMatrix4x3fv QGLContextPrivate::extensionFuncs(ctx).qt_glUniformMatrix4x3fv
#define glBindAttribLocation QGLContextPrivate::extensionFuncs(ctx).qt_glBindAttribLocation
#define glGetAttribLocation QGLContextPrivate::extensionFuncs(ctx).qt_glGetAttribLocation
#define glVertexAttrib1fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib1fv
#define glVertexAttrib2fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib2fv
#define glVertexAttrib3fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib3fv
#define glVertexAttrib4fv QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttrib4fv
#define glVertexAttribPointer QGLContextPrivate::extensionFuncs(ctx).qt_glVertexAttribPointer
#define glDisableVertexAttribArray QGLContextPrivate::extensionFuncs(ctx).qt_glDisableVertexAttribArray
#define glEnableVertexAttribArray QGLContextPrivate::extensionFuncs(ctx).qt_glEnableVertexAttribArray
#else // QT_OPENGL_ES_2
#define glGetProgramBinaryOES QGLContextPrivate::extensionFuncs(ctx).qt_glGetProgramBinaryOES
#define glProgramBinaryOES QGLContextPrivate::extensionFuncs(ctx).qt_glProgramBinaryOES
#endif // QT_OPENGL_ES_2
#if !defined(QT_OPENGL_ES_2)
#define glStencilOpSeparate QGLContextPrivate::extensionFuncs(ctx).qt_glStencilOpSeparate
#define glBlendColor QGLContextPrivate::extensionFuncs(ctx).qt_glBlendColor
#endif
#if defined(QT_OPENGL_ES_2)
#define glClearDepth glClearDepthf
#endif
#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT
#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT
#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT
#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT
#if !defined(QT_OPENGL_ES)
#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
#endif
#ifndef QT_NO_EGL
// OES_EGL_image
#define glEGLImageTargetTexture2DOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetTexture2DOES
#define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES
#endif
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool Q_OPENGL_EXPORT qt_resolve_buffer_extensions(QGLContext *ctx);
bool qt_resolve_version_1_3_functions(QGLContext *ctx);
bool Q_OPENGL_EXPORT qt_resolve_version_2_0_functions(QGLContext *ctx);
bool qt_resolve_stencil_face_extension(QGLContext *ctx);
bool qt_resolve_frag_program_extensions(QGLContext *ctx);
bool qt_resolve_glsl_extensions(QGLContext *ctx);
#ifndef QT_NO_EGL
Q_OPENGL_EXPORT bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx);
#endif
QT_END_NAMESPACE
#endif // QGL_EXTENSIONS_P_H

File diff suppressed because it is too large Load diff

View file

@ -1,160 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLFRAMEBUFFEROBJECT_H
#define QGLFRAMEBUFFEROBJECT_H
#include <QtOpenGL/qgl.h>
#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGLFramebufferObjectPrivate;
class QGLFramebufferObjectFormat;
class Q_OPENGL_EXPORT QGLFramebufferObject : public QPaintDevice
{
Q_DECLARE_PRIVATE(QGLFramebufferObject)
public:
enum Attachment {
NoAttachment,
CombinedDepthStencil,
Depth
};
QGLFramebufferObject(const QSize &size, GLenum target = GL_TEXTURE_2D);
QGLFramebufferObject(int width, int height, GLenum target = GL_TEXTURE_2D);
#if !defined(QT_OPENGL_ES)
QGLFramebufferObject(const QSize &size, Attachment attachment,
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8);
QGLFramebufferObject(int width, int height, Attachment attachment,
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA8);
#else
QGLFramebufferObject(const QSize &size, Attachment attachment,
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
QGLFramebufferObject(int width, int height, Attachment attachment,
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
#endif
QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format);
QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format);
virtual ~QGLFramebufferObject();
QGLFramebufferObjectFormat format() const;
bool isValid() const;
bool isBound() const;
bool bind();
bool release();
GLuint texture() const;
QSize size() const;
QImage toImage() const;
Attachment attachment() const;
QPaintEngine *paintEngine() const;
GLuint handle() const;
static bool bindDefault();
static bool hasOpenGLFramebufferObjects();
void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
static bool hasOpenGLFramebufferBlit();
static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
QGLFramebufferObject *source, const QRect &sourceRect,
GLbitfield buffers = GL_COLOR_BUFFER_BIT,
GLenum filter = GL_NEAREST);
protected:
int metric(PaintDeviceMetric metric) const;
int devType() const { return QInternal::FramebufferObject; }
private:
Q_DISABLE_COPY(QGLFramebufferObject)
QScopedPointer<QGLFramebufferObjectPrivate> d_ptr;
friend class QGLPaintDevice;
friend class QGLFBOGLPaintDevice;
};
class QGLFramebufferObjectFormatPrivate;
class Q_OPENGL_EXPORT QGLFramebufferObjectFormat
{
public:
QGLFramebufferObjectFormat();
QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other);
QGLFramebufferObjectFormat &operator=(const QGLFramebufferObjectFormat &other);
~QGLFramebufferObjectFormat();
void setSamples(int samples);
int samples() const;
void setMipmap(bool enabled);
bool mipmap() const;
void setAttachment(QGLFramebufferObject::Attachment attachment);
QGLFramebufferObject::Attachment attachment() const;
void setTextureTarget(GLenum target);
GLenum textureTarget() const;
void setInternalTextureFormat(GLenum internalTextureFormat);
GLenum internalTextureFormat() const;
bool operator==(const QGLFramebufferObjectFormat& other) const;
bool operator!=(const QGLFramebufferObjectFormat& other) const;
private:
QGLFramebufferObjectFormatPrivate *d;
void detach();
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QGLFRAMEBUFFEROBJECT_H

View file

@ -1,160 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLFRAMEBUFFEROBJECT_P_H
#define QGLFRAMEBUFFEROBJECT_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists 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 <qglframebufferobject.h>
#include <qglpaintdevice_p.h>
#include <qgl_p.h>
QT_END_INCLUDE_NAMESPACE
#ifndef QT_OPENGL_ES
#define DEFAULT_FORMAT GL_RGBA8
#else
#define DEFAULT_FORMAT GL_RGBA
#endif
class QGLFramebufferObjectFormatPrivate
{
public:
QGLFramebufferObjectFormatPrivate()
: ref(1),
samples(0),
attachment(QGLFramebufferObject::NoAttachment),
target(GL_TEXTURE_2D),
internal_format(DEFAULT_FORMAT),
mipmap(false)
{
}
QGLFramebufferObjectFormatPrivate
(const QGLFramebufferObjectFormatPrivate *other)
: ref(1),
samples(other->samples),
attachment(other->attachment),
target(other->target),
internal_format(other->internal_format),
mipmap(other->mipmap)
{
}
bool equals(const QGLFramebufferObjectFormatPrivate *other)
{
return samples == other->samples &&
attachment == other->attachment &&
target == other->target &&
internal_format == other->internal_format &&
mipmap == other->mipmap;
}
QAtomicInt ref;
int samples;
QGLFramebufferObject::Attachment attachment;
GLenum target;
GLenum internal_format;
uint mipmap : 1;
};
class QGLFBOGLPaintDevice : public QGLPaintDevice
{
public:
virtual QPaintEngine* paintEngine() const {return fbo->paintEngine();}
virtual QSize size() const {return fbo->size();}
virtual QGLContext* context() const;
virtual QGLFormat format() const {return fboFormat;}
virtual bool alphaRequested() const { return reqAlpha; }
void setFBO(QGLFramebufferObject* f,
QGLFramebufferObject::Attachment attachment);
private:
QGLFramebufferObject* fbo;
QGLFormat fboFormat;
bool reqAlpha;
};
class QGLFramebufferObjectPrivate
{
public:
QGLFramebufferObjectPrivate() : fbo_guard(0), texture(0), depth_buffer(0), stencil_buffer(0)
, color_buffer(0), valid(false), engine(0) {}
~QGLFramebufferObjectPrivate() {}
void init(QGLFramebufferObject *q, const QSize& sz,
QGLFramebufferObject::Attachment attachment,
GLenum internal_format, GLenum texture_target,
GLint samples = 0, bool mipmap = false);
bool checkFramebufferStatus() const;
QGLSharedResourceGuard fbo_guard;
GLuint texture;
GLuint depth_buffer;
GLuint stencil_buffer;
GLuint color_buffer;
GLenum target;
QSize size;
QGLFramebufferObjectFormat format;
uint valid : 1;
QGLFramebufferObject::Attachment fbo_attachment;
mutable QPaintEngine *engine;
QGLFBOGLPaintDevice glDevice;
inline GLuint fbo() const { return fbo_guard.id(); }
};
QT_END_NAMESPACE
#endif // QGLFRAMEBUFFEROBJECT_P_H

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,250 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qglpaintdevice_p.h>
#include <qgl_p.h>
#include <qglpixelbuffer_p.h>
#include <qglframebufferobject_p.h>
#ifdef Q_WS_X11
#include <qpixmapdata_x11gl_p.h>
#endif
#if !defined(QT_OPENGL_ES_1)
#include <qpixmapdata_gl_p.h>
#include <qwindowsurface_gl_p.h>
#endif
QT_BEGIN_NAMESPACE
QGLPaintDevice::QGLPaintDevice()
: m_thisFBO(0)
{
}
QGLPaintDevice::~QGLPaintDevice()
{
}
int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
{
switch(metric) {
case PdmWidth:
return size().width();
case PdmHeight:
return size().height();
case PdmDepth: {
const QGLFormat f = format();
return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
}
default:
qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
return 0;
}
}
void QGLPaintDevice::beginPaint()
{
// Make sure our context is the current one:
QGLContext *ctx = context();
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
// 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_ptr->current_fbo = m_thisFBO;
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
}
// Set the default fbo for the context to m_thisFBO so that
// if some raw GL code between beginNativePainting() and
// endNativePainting() calls QGLFramebufferObject::release(),
// painting will revert to the window surface's fbo.
ctx->d_ptr->default_fbo = m_thisFBO;
}
void QGLPaintDevice::ensureActiveTarget()
{
QGLContext* ctx = context();
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
if (ctx->d_ptr->current_fbo != m_thisFBO) {
ctx->d_ptr->current_fbo = m_thisFBO;
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_thisFBO);
}
ctx->d_ptr->default_fbo = m_thisFBO;
}
void QGLPaintDevice::endPaint()
{
// Make sure the FBO bound at beginPaint is re-bound again here:
QGLContext *ctx = context();
if (m_previousFBO != ctx->d_func()->current_fbo) {
ctx->d_ptr->current_fbo = m_previousFBO;
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_previousFBO);
}
ctx->d_ptr->default_fbo = 0;
}
QGLFormat QGLPaintDevice::format() const
{
return context()->format();
}
bool QGLPaintDevice::alphaRequested() const
{
return context()->d_func()->reqFormat.alpha();
}
bool QGLPaintDevice::isFlipped() const
{
return false;
}
////////////////// QGLWidgetGLPaintDevice //////////////////
QGLWidgetGLPaintDevice::QGLWidgetGLPaintDevice()
{
}
QPaintEngine* QGLWidgetGLPaintDevice::paintEngine() const
{
return glWidget->paintEngine();
}
void QGLWidgetGLPaintDevice::setWidget(QGLWidget* w)
{
glWidget = w;
}
void QGLWidgetGLPaintDevice::beginPaint()
{
QGLPaintDevice::beginPaint();
if (!glWidget->d_func()->disable_clear_on_painter_begin && glWidget->autoFillBackground()) {
if (glWidget->testAttribute(Qt::WA_TranslucentBackground))
glClearColor(0.0, 0.0, 0.0, 0.0);
else {
const QColor &c = glWidget->palette().brush(glWidget->backgroundRole()).color();
float alpha = c.alphaF();
glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
}
if (context()->d_func()->workaround_needsFullClearOnEveryFrame)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
else
glClear(GL_COLOR_BUFFER_BIT);
}
}
void QGLWidgetGLPaintDevice::endPaint()
{
if (glWidget->autoBufferSwap())
glWidget->swapBuffers();
QGLPaintDevice::endPaint();
}
QSize QGLWidgetGLPaintDevice::size() const
{
return glWidget->size();
}
QGLContext* QGLWidgetGLPaintDevice::context() const
{
return const_cast<QGLContext*>(glWidget->context());
}
// returns the QGLPaintDevice for the given QPaintDevice
QGLPaintDevice* QGLPaintDevice::getDevice(QPaintDevice* pd)
{
QGLPaintDevice* glpd = 0;
switch(pd->devType()) {
case QInternal::Widget:
// Should not be called on a non-gl widget:
Q_ASSERT(qobject_cast<QGLWidget*>(static_cast<QWidget*>(pd)));
glpd = &(static_cast<QGLWidget*>(pd)->d_func()->glDevice);
break;
case QInternal::Pbuffer:
glpd = &(static_cast<QGLPixelBuffer*>(pd)->d_func()->glDevice);
break;
case QInternal::FramebufferObject:
glpd = &(static_cast<QGLFramebufferObject*>(pd)->d_func()->glDevice);
break;
case QInternal::Pixmap: {
#if !defined(QT_OPENGL_ES_1)
QPixmapData* pmd = static_cast<QPixmap*>(pd)->pixmapData();
if (pmd->classId() == QPixmapData::OpenGLClass)
glpd = static_cast<QGLPixmapData*>(pmd)->glDevice();
#ifdef Q_WS_X11
else if (pmd->classId() == QPixmapData::X11Class)
glpd = static_cast<QX11GLPixmapData*>(pmd);
#endif
else
qWarning("Pixmap type not supported for GL rendering");
#else
qWarning("Pixmap render targets not supported on OpenGL ES 1.x");
#endif
break;
}
default:
qWarning("QGLPaintDevice::getDevice() - Unknown device type %d", pd->devType());
break;
}
return glpd;
}
QT_END_NAMESPACE

View file

@ -1,115 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLPAINTDEVICE_P_H
#define QGLPAINTDEVICE_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 QtOpenGL module. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
//
#include <qpaintdevice.h>
#include <qgl.h>
QT_BEGIN_NAMESPACE
class Q_OPENGL_EXPORT QGLPaintDevice : public QPaintDevice
{
public:
QGLPaintDevice();
virtual ~QGLPaintDevice();
int devType() const {return QInternal::OpenGL;}
virtual void beginPaint();
virtual void ensureActiveTarget();
virtual void endPaint();
virtual QGLContext* context() const = 0;
virtual QGLFormat format() const;
virtual QSize size() const = 0;
virtual bool alphaRequested() const;
virtual bool isFlipped() const;
// returns the QGLPaintDevice for the given QPaintDevice
static QGLPaintDevice* getDevice(QPaintDevice*);
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
GLuint m_previousFBO;
GLuint m_thisFBO;
};
// Wraps a QGLWidget
class QGLWidget;
class QGLWidgetGLPaintDevice : public QGLPaintDevice
{
public:
QGLWidgetGLPaintDevice();
virtual QPaintEngine* paintEngine() const;
// QGLWidgets need to do swapBufers in endPaint:
virtual void beginPaint();
virtual void endPaint();
virtual QSize size() const;
virtual QGLContext* context() const;
void setWidget(QGLWidget*);
private:
friend class QGLWidget;
QGLWidget *glWidget;
};
QT_END_NAMESPACE
#endif // QGLPAINTDEVICE_P_H

View file

@ -1,567 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\class QGLPixelBuffer
\brief The QGLPixelBuffer class encapsulates an OpenGL pbuffer.
\since 4.1
\ingroup painting-3D
Rendering into a pbuffer is normally done using full hardware
acceleration. This can be significantly faster than rendering
into a QPixmap.
There are three approaches to using this class:
\list 1
\o \bold{We can draw into the pbuffer and convert it to a QImage
using toImage().} This is normally much faster than calling
QGLWidget::renderPixmap().
\o \bold{We can draw into the pbuffer and copy the contents into
an OpenGL texture using updateDynamicTexture().} This allows
us to create dynamic textures and works on all systems
with pbuffer support.
\o \bold{On systems that support it, we can bind the pbuffer to
an OpenGL texture.} The texture is then updated automatically
when the pbuffer contents change, eliminating the need for
additional copy operations. This is supported only on Windows
and Mac OS X systems that provide the \c render_texture
extension. Note that under Windows, a multi-sampled pbuffer
can't be used in conjunction with the \c render_texture
extension. If a multi-sampled pbuffer is requested under
Windows, the \c render_texture extension is turned off for that
pbuffer.
\endlist
\section1 Threading
As of Qt 4.8, it's possible to render into a QGLPixelBuffer using
a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES
2.0 is required for this to work. Also, under X11, it's necessary
to set the Qt::AA_X11InitThreads application attribute.
Pbuffers are provided by the OpenGL \c pbuffer extension; call
hasOpenGLPbuffer() to find out if the system provides pbuffers.
\sa {opengl/pbuffers}{Pbuffers Example}
*/
#include "qopenglcommon_p.h"
#if !defined(QT_OPENGL_ES_1)
#include <qpaintengineex_opengl2_p.h>
#endif
#include <qglpixelbuffer.h>
#include <qglpixelbuffer_p.h>
#include <qfont_p.h>
#include <qimage.h>
#ifndef QT_OPENGL_ES_2
#include <qpaintengine_opengl_p.h>
#endif
QT_BEGIN_NAMESPACE
#if !defined(QT_OPENGL_ES_2)
extern void qgl_cleanup_glyph_cache(QGLContext *);
#else
void qgl_cleanup_glyph_cache(QGLContext *) {}
#endif
extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
QGLContext* QGLPBufferGLPaintDevice::context() const
{
return pbuf->d_func()->qctx;
}
void QGLPBufferGLPaintDevice::endPaint() {
glFlush();
QGLPaintDevice::endPaint();
}
void QGLPBufferGLPaintDevice::setPBuffer(QGLPixelBuffer* pb)
{
pbuf = pb;
}
void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
{
Q_Q(QGLPixelBuffer);
if(init(size, format, shareWidget)) {
req_size = size;
req_format = format;
req_shareWidget = shareWidget;
invalid = false;
qctx = new QGLContext(format);
qctx->d_func()->sharing = (shareWidget != 0);
if (shareWidget != 0 && shareWidget->d_func()->glcx) {
QGLContextGroup::addShare(qctx, shareWidget->d_func()->glcx);
shareWidget->d_func()->glcx->d_func()->sharing = true;
}
glDevice.setPBuffer(q);
qctx->d_func()->paintDevice = q;
qctx->d_func()->valid = true;
#if defined(Q_WS_X11) && defined(QT_NO_EGL)
qctx->d_func()->cx = ctx;
qctx->d_func()->pbuf = (void *) pbuf;
qctx->d_func()->vi = 0;
#elif !defined(QT_NO_EGL)
qctx->d_func()->eglContext = ctx;
qctx->d_func()->eglSurface = pbuf;
#endif
}
}
/*!
Constructs an OpenGL pbuffer of the given \a size. If no \a
format is specified, the \l{QGLFormat::defaultFormat()}{default
format} is used. If the \a shareWidget parameter points to a
valid QGLWidget, the pbuffer will share its context with \a
shareWidget.
If you intend to bind this pbuffer as a dynamic texture, the width
and height components of \c size must be powers of two (e.g., 512
x 128).
\sa size(), format()
*/
QGLPixelBuffer::QGLPixelBuffer(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
: d_ptr(new QGLPixelBufferPrivate(this))
{
Q_D(QGLPixelBuffer);
d->common_init(size, format, shareWidget);
}
/*! \overload
Constructs an OpenGL pbuffer with the \a width and \a height. If
no \a format is specified, the
\l{QGLFormat::defaultFormat()}{default format} is used. If the \a
shareWidget parameter points to a valid QGLWidget, the pbuffer
will share its context with \a shareWidget.
If you intend to bind this pbuffer as a dynamic texture, the width
and height components of \c size must be powers of two (e.g., 512
x 128).
\sa size(), format()
*/
QGLPixelBuffer::QGLPixelBuffer(int width, int height, const QGLFormat &format, QGLWidget *shareWidget)
: d_ptr(new QGLPixelBufferPrivate(this))
{
Q_D(QGLPixelBuffer);
d->common_init(QSize(width, height), format, shareWidget);
}
/*! \fn QGLPixelBuffer::~QGLPixelBuffer()
Destroys the pbuffer and frees any allocated resources.
*/
QGLPixelBuffer::~QGLPixelBuffer()
{
Q_D(QGLPixelBuffer);
// defined in qpaintengine_opengl.cpp
QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
if (current != d->qctx)
makeCurrent();
qgl_cleanup_glyph_cache(d->qctx);
d->cleanup();
delete d->qctx;
if (current && current != d->qctx)
current->makeCurrent();
}
/*! \fn bool QGLPixelBuffer::makeCurrent()
Makes this pbuffer the current OpenGL rendering context. Returns
true on success; otherwise returns false.
\sa QGLContext::makeCurrent(), doneCurrent()
*/
bool QGLPixelBuffer::makeCurrent()
{
Q_D(QGLPixelBuffer);
if (d->invalid)
return false;
d->qctx->makeCurrent();
return true;
}
/*! \fn bool QGLPixelBuffer::doneCurrent()
Makes no context the current OpenGL context. Returns true on
success; otherwise returns false.
*/
bool QGLPixelBuffer::doneCurrent()
{
Q_D(QGLPixelBuffer);
if (d->invalid)
return false;
d->qctx->doneCurrent();
return true;
}
/*!
Generates and binds a 2D GL texture that is the same size as the
pbuffer, and returns the texture's ID. This can be used in
conjunction with bindToDynamicTexture() and
updateDynamicTexture().
\sa size()
*/
#if defined(Q_WS_X11) && defined(QT_NO_EGL)
GLuint QGLPixelBuffer::generateDynamicTexture() const
{
Q_D(const QGLPixelBuffer);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_FLOAT, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return texture;
}
#endif
/*! \fn bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
Binds the texture specified by \a texture_id to this pbuffer.
Returns true on success; otherwise returns false.
The texture must be of the same size and format as the pbuffer.
To unbind the texture, call releaseFromDynamicTexture(). While
the texture is bound, it is updated automatically when the
pbuffer contents change, eliminating the need for additional copy
operations.
Example:
\snippet doc/src/snippets/code/src_opengl_qglpixelbuffer.cpp 0
\warning This function uses the \c {render_texture} extension,
which is currently not supported under X11. An alternative that
works on all systems (including X11) is to manually copy the
pbuffer contents to a texture using updateDynamicTexture().
\warning For the bindToDynamicTexture() call to succeed on the
Mac OS X, the pbuffer needs a shared context, i.e. the
QGLPixelBuffer must be created with a share widget.
\sa generateDynamicTexture(), releaseFromDynamicTexture()
*/
/*! \fn void QGLPixelBuffer::releaseFromDynamicTexture()
Releases the pbuffer from any previously bound texture.
\sa bindToDynamicTexture()
*/
/*! \fn bool QGLPixelBuffer::hasOpenGLPbuffers()
Returns true if the OpenGL \c pbuffer extension is present on
this system; otherwise returns false.
*/
/*!
Copies the pbuffer contents into the texture specified with \a
texture_id.
The texture must be of the same size and format as the pbuffer.
Example:
\snippet doc/src/snippets/code/src_opengl_qglpixelbuffer.cpp 1
An alternative on Windows and Mac OS X systems that support the
\c render_texture extension is to use bindToDynamicTexture() to
get dynamic updates of the texture.
\sa generateDynamicTexture(), bindToDynamicTexture()
*/
void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
{
Q_D(const QGLPixelBuffer);
if (d->invalid)
return;
glBindTexture(GL_TEXTURE_2D, texture_id);
#ifndef QT_OPENGL_ES
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0);
#else
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
#endif
}
/*!
Returns the size of the pbuffer.
*/
QSize QGLPixelBuffer::size() const
{
Q_D(const QGLPixelBuffer);
return d->req_size;
}
/*!
Returns the contents of the pbuffer as a QImage.
*/
QImage QGLPixelBuffer::toImage() const
{
Q_D(const QGLPixelBuffer);
if (d->invalid)
return QImage();
const_cast<QGLPixelBuffer *>(this)->makeCurrent();
return qt_gl_read_framebuffer(d->req_size, d->format.alpha(), true);
}
/*!
Returns the native pbuffer handle.
*/
Qt::HANDLE QGLPixelBuffer::handle() const
{
Q_D(const QGLPixelBuffer);
if (d->invalid)
return 0;
return (Qt::HANDLE) d->pbuf;
}
/*!
Returns true if this pbuffer is valid; otherwise returns false.
*/
bool QGLPixelBuffer::isValid() const
{
Q_D(const QGLPixelBuffer);
return !d->invalid;
}
/*! \reimp */
QPaintEngine *QGLPixelBuffer::paintEngine() const
{
#if defined(QT_OPENGL_ES_1)
return qt_buffer_engine()->engine();
#elif defined(QT_OPENGL_ES_2)
return qt_buffer_2_engine()->engine();
#else
if (qt_gl_preferGL2Engine())
return qt_buffer_2_engine()->engine();
else
return qt_buffer_engine()->engine();
#endif
}
/*! \reimp */
int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
{
Q_D(const QGLPixelBuffer);
float dpmx = qt_defaultDpiX()*100./2.54;
float dpmy = qt_defaultDpiY()*100./2.54;
int w = d->req_size.width();
int h = d->req_size.height();
switch (metric) {
case PdmWidth:
return w;
case PdmHeight:
return h;
case PdmWidthMM:
return qRound(w * 1000 / dpmx);
case PdmHeightMM:
return qRound(h * 1000 / dpmy);
case PdmNumColors:
return 0;
case PdmDepth:
return 32;//d->depth;
case PdmDpiX:
return qRound(dpmx * 0.0254);
case PdmDpiY:
return qRound(dpmy * 0.0254);
case PdmPhysicalDpiX:
return qRound(dpmx * 0.0254);
case PdmPhysicalDpiY:
return qRound(dpmy * 0.0254);
default:
qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
break;
}
return 0;
}
/*!
Generates and binds a 2D GL texture to the current context, based
on \a image. The generated texture id is returned and can be used
in later glBindTexture() calls.
The \a target parameter specifies the texture target.
Equivalent to calling QGLContext::bindTexture().
\sa deleteTexture()
*/
GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target)
{
Q_D(QGLPixelBuffer);
#ifndef QT_OPENGL_ES
return d->qctx->bindTexture(image, target, GLint(GL_RGBA8));
#else
return d->qctx->bindTexture(image, target, GL_RGBA);
#endif
}
/*! \overload
Generates and binds a 2D GL texture based on \a pixmap.
Equivalent to calling QGLContext::bindTexture().
\sa deleteTexture()
*/
GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target)
{
Q_D(QGLPixelBuffer);
#ifndef QT_OPENGL_ES
return d->qctx->bindTexture(pixmap, target, GLint(GL_RGBA8));
#else
return d->qctx->bindTexture(pixmap, target, GL_RGBA);
#endif
}
/*! \overload
Reads the DirectDrawSurface (DDS) compressed file \a fileName and
generates a 2D GL texture from it.
Equivalent to calling QGLContext::bindTexture().
\sa deleteTexture()
*/
GLuint QGLPixelBuffer::bindTexture(const QString &fileName)
{
Q_D(QGLPixelBuffer);
return d->qctx->bindTexture(fileName);
}
/*!
Removes the texture identified by \a texture_id from the texture cache.
Equivalent to calling QGLContext::deleteTexture().
*/
void QGLPixelBuffer::deleteTexture(GLuint texture_id)
{
Q_D(QGLPixelBuffer);
d->qctx->deleteTexture(texture_id);
}
/*!
\since 4.4
Draws the given texture, \a textureId, to the given target rectangle,
\a target, in OpenGL model space. The \a textureTarget should be a 2D
texture target.
Equivalent to the corresponding QGLContext::drawTexture().
*/
void QGLPixelBuffer::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
{
Q_D(QGLPixelBuffer);
d->qctx->drawTexture(target, textureId, textureTarget);
}
/*!
\since 4.4
Draws the given texture, \a textureId, at the given \a point in OpenGL model
space. The textureTarget parameter should be a 2D texture target.
Equivalent to the corresponding QGLContext::drawTexture().
*/
void QGLPixelBuffer::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
{
Q_D(QGLPixelBuffer);
d->qctx->drawTexture(point, textureId, textureTarget);
}
/*!
Returns the format of the pbuffer. The format may be different
from the one that was requested.
*/
QGLFormat QGLPixelBuffer::format() const
{
Q_D(const QGLPixelBuffer);
return d->format;
}
/*! \fn int QGLPixelBuffer::devType() const
\internal
*/
QT_END_NAMESPACE

View file

@ -1,109 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLPIXELBUFFER_H
#define QGLPIXELBUFFER_H
#include <QtOpenGL/qgl.h>
#include <QtGui/qpaintdevice.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
class QGLPixelBufferPrivate;
class Q_OPENGL_EXPORT QGLPixelBuffer : public QPaintDevice
{
Q_DECLARE_PRIVATE(QGLPixelBuffer)
public:
QGLPixelBuffer(const QSize &size, const QGLFormat &format = QGLFormat::defaultFormat(),
QGLWidget *shareWidget = 0);
QGLPixelBuffer(int width, int height, const QGLFormat &format = QGLFormat::defaultFormat(),
QGLWidget *shareWidget = 0);
virtual ~QGLPixelBuffer();
bool isValid() const;
bool makeCurrent();
bool doneCurrent();
GLuint generateDynamicTexture() const;
bool bindToDynamicTexture(GLuint texture);
void releaseFromDynamicTexture();
void updateDynamicTexture(GLuint texture_id) const;
GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D);
GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D);
GLuint bindTexture(const QString &fileName);
void deleteTexture(GLuint texture_id);
void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
QSize size() const;
Qt::HANDLE handle() const;
QImage toImage() const;
QPaintEngine *paintEngine() const;
QGLFormat format() const;
static bool hasOpenGLPbuffers();
protected:
int metric(PaintDeviceMetric metric) const;
int devType() const { return QInternal::Pbuffer; }
private:
Q_DISABLE_COPY(QGLPixelBuffer)
QScopedPointer<QGLPixelBufferPrivate> d_ptr;
friend class QGLDrawable;
friend class QGLWindowSurface;
friend class QGLPaintDevice;
friend class QGLPBufferGLPaintDevice;
friend class QGLContextPrivate;
};
QT_END_NAMESPACE
QT_END_HEADER
#endif // QGLPIXELBUFFER_H

View file

@ -1,226 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtOpenGL module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company 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.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qdebug.h>
#include "qglpixelbuffer.h"
#include "qglpixelbuffer_p.h"
#include "qgl_egl_p.h"
#include <qimage.h>
#include <qgl_p.h>
QT_BEGIN_NAMESPACE
#ifdef EGL_BIND_TO_TEXTURE_RGBA
#define QGL_RENDER_TEXTURE 1
#else
#define QGL_RENDER_TEXTURE 0
#endif
bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget)
{
// Create the EGL context.
ctx = new QEglContext();
ctx->setApi(QEgl::OpenGL);
// Find the shared context.
QEglContext *shareContext = 0;
if (shareWidget && shareWidget->d_func()->glcx)
shareContext = shareWidget->d_func()->glcx->d_func()->eglContext;
// Choose an appropriate configuration. We use the best format
// we can find, even if it is greater than the requested format.
// We try for a pbuffer that is capable of texture rendering if possible.
textureFormat = EGL_NONE;
if (shareContext) {
// Use the same configuration as the widget we are sharing with.
ctx->setConfig(shareContext->config());
#if QGL_RENDER_TEXTURE
if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGBA) == EGL_TRUE)
textureFormat = EGL_TEXTURE_RGBA;
else if (ctx->configAttrib(EGL_BIND_TO_TEXTURE_RGB) == EGL_TRUE)
textureFormat = EGL_TEXTURE_RGB;
#endif
} else {
QEglProperties configProps;
qt_eglproperties_set_glformat(configProps, f);
configProps.setDeviceType(QInternal::Pbuffer);
configProps.setRenderableType(ctx->api());
bool ok = false;
#if QGL_RENDER_TEXTURE
textureFormat = EGL_TEXTURE_RGBA;
configProps.setValue(EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
if (!ok) {
// Try again with RGB texture rendering.
textureFormat = EGL_TEXTURE_RGB;
configProps.removeValue(EGL_BIND_TO_TEXTURE_RGBA);
configProps.setValue(EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
ok = ctx->chooseConfig(configProps, QEgl::BestPixelFormat);
if (!ok) {
// One last try for a pbuffer with no texture rendering.
configProps.removeValue(EGL_BIND_TO_TEXTURE_RGB);
textureFormat = EGL_NONE;
}
}
#endif
if (!ok) {
if (!ctx->chooseConfig(configProps, QEgl::BestPixelFormat)) {
delete ctx;
ctx = 0;
return false;
}
}
}
// Retrieve the actual format properties.
qt_glformat_from_eglconfig(format, ctx->config());
// Create the attributes needed for the pbuffer.
QEglProperties attribs;
attribs.setValue(EGL_WIDTH, size.width());
attribs.setValue(EGL_HEIGHT, size.height());
#if QGL_RENDER_TEXTURE
if (textureFormat != EGL_NONE) {
attribs.setValue(EGL_TEXTURE_FORMAT, textureFormat);
attribs.setValue(EGL_TEXTURE_TARGET, EGL_TEXTURE_2D);
}
#endif
// Create the pbuffer surface.
pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties());
#if QGL_RENDER_TEXTURE
if (pbuf == EGL_NO_SURFACE && textureFormat != EGL_NONE) {
// Try again with texture rendering disabled.
textureFormat = EGL_NONE;
attribs.removeValue(EGL_TEXTURE_FORMAT);
attribs.removeValue(EGL_TEXTURE_TARGET);
pbuf = eglCreatePbufferSurface(ctx->display(), ctx->config(), attribs.properties());
}
#endif
if (pbuf == EGL_NO_SURFACE) {
qWarning() << "QGLPixelBufferPrivate::init(): Unable to create EGL pbuffer surface:" << QEgl::errorString();
return false;
}
// Create a new context for the configuration.
if (!ctx->createContext(shareContext)) {
delete ctx;
ctx = 0;
return false;
}
return true;
}
bool QGLPixelBufferPrivate::cleanup()
{
// No need to destroy "pbuf" here - it is done in QGLContext::reset().
return true;
}
bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
{
#if QGL_RENDER_TEXTURE
Q_D(QGLPixelBuffer);
if (d->invalid || d->textureFormat == EGL_NONE || !d->ctx)
return false;
glBindTexture(GL_TEXTURE_2D, texture_id);
return eglBindTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER);
#else
Q_UNUSED(texture_id);
return false;
#endif
}
void QGLPixelBuffer::releaseFromDynamicTexture()
{
#if QGL_RENDER_TEXTURE
Q_D(QGLPixelBuffer);
if (d->invalid || d->textureFormat == EGL_NONE || !d->ctx)
return;
eglReleaseTexImage(d->ctx->display(), d->pbuf, EGL_BACK_BUFFER);
#endif
}
GLuint QGLPixelBuffer::generateDynamicTexture() const
{
#if QGL_RENDER_TEXTURE
Q_D(const QGLPixelBuffer);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
if (d->textureFormat == EGL_TEXTURE_RGB)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, d->req_size.width(), d->req_size.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
else
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
return texture;
#else
return 0;
#endif
}
bool QGLPixelBuffer::hasOpenGLPbuffers()
{
// See if we have at least 1 configuration that matches the default format.
EGLDisplay dpy = QEgl::display();
if (dpy == EGL_NO_DISPLAY)
return false;
QEglProperties configProps;
qt_eglproperties_set_glformat(configProps, QGLFormat::defaultFormat());
configProps.setDeviceType(QInternal::Pbuffer);
configProps.setRenderableType(QEgl::OpenGL);
do {
EGLConfig cfg = 0;
EGLint matching = 0;
if (eglChooseConfig(dpy, configProps.properties(),
&cfg, 1, &matching) && matching > 0)
return true;
} while (configProps.reduceConfiguration());
return false;
}
QT_END_NAMESPACE

Some files were not shown because too many files have changed in this diff Show more