mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-23 18:32:55 +00:00
remove the opengl component
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
parent
8c8cfc8f83
commit
71ffb62f31
171 changed files with 87 additions and 61262 deletions
|
@ -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
2
README
|
@ -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:
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 ************************************
|
||||
|
|
|
@ -2789,7 +2789,6 @@ int QWidget::metric(PaintDeviceMetric m) const
|
|||
|
||||
void QWidgetPrivate::createSysExtra()
|
||||
{
|
||||
extra->compress_events = true;
|
||||
extra->xDndProxy = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
||||
|
|
|
@ -184,12 +184,10 @@ public:
|
|||
enum Type {
|
||||
X11,
|
||||
PostScript,
|
||||
OpenGL,
|
||||
Picture,
|
||||
SVG,
|
||||
Raster,
|
||||
Pdf,
|
||||
OpenGL2,
|
||||
PaintBuffer,
|
||||
|
||||
User = 50, // first user type id
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1293,6 +1293,7 @@ QFont::StyleHint QFont::styleHint() const
|
|||
\value System the font matcher prefers system fonts.
|
||||
*/
|
||||
|
||||
#warning opengl leftovers
|
||||
/*!
|
||||
\enum QFont::StyleStrategy
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
|
@ -1,2 +0,0 @@
|
|||
plugin qmlshadersplugin
|
||||
|
|
@ -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>
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
||||
)
|
|
@ -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)
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
@ -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
|
5679
src/opengl/qgl.cpp
5679
src/opengl/qgl.cpp
File diff suppressed because it is too large
Load diff
543
src/opengl/qgl.h
543
src/opengl/qgl.h
|
@ -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
|
|
@ -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 ®ion)
|
||||
{
|
||||
if (!valid || !eglContext)
|
||||
return;
|
||||
|
||||
eglContext->swapBuffersRegion2NOK(eglSurfaceForDevice(), ®ion);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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 ®ion);
|
||||
|
||||
#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
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
@ -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
|
|
@ -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
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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
Loading…
Add table
Reference in a new issue