diff options
author | Andy Nichols <andy.nichols@qt.io> | 2016-04-03 18:06:46 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2016-12-13 15:43:15 +0000 |
commit | 3f57f2b7cc3899af154257a3c858bd23d9f03a62 (patch) | |
tree | 45ba7f7a37110c81963bf644b8830201504e117f /src/plugins/scenegraph | |
parent | bff7302fc277d18b5bd4ad95d35b9e1bbc2be001 (diff) |
OpenVG Scenegraph Adaptation
This is an OpenVG backend for the Qt Quick 2 scenegraph.
Should be feature complete now, but there are still some issues that
could be improved in future commits:
If Rectangle nodes are rendered with a non-affine transform, they will
be rendered incorrectly. This is because paths expect affine
transformations.
The Glyph cache is a bit cheeky in that it's caching paths, but doing
so per font size. It shoudln't need to, but right now I've not though
up a good way of getting the transform/scale needed when rendering yet.
Change-Id: Ie3c4f2df35d14279b0f9f55e0e10a873328c025b
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/plugins/scenegraph')
39 files changed, 6045 insertions, 0 deletions
diff --git a/src/plugins/scenegraph/openvg/openvg.json b/src/plugins/scenegraph/openvg/openvg.json new file mode 100644 index 0000000000..224afbf784 --- /dev/null +++ b/src/plugins/scenegraph/openvg/openvg.json @@ -0,0 +1,3 @@ +{ + "Keys": ["openvg"] +} diff --git a/src/plugins/scenegraph/openvg/openvg.pro b/src/plugins/scenegraph/openvg/openvg.pro new file mode 100644 index 0000000000..fb9b3b93f5 --- /dev/null +++ b/src/plugins/scenegraph/openvg/openvg.pro @@ -0,0 +1,54 @@ +TARGET = qsgopenvgbackend + +QT += gui-private core-private qml-private quick-private + +PLUGIN_TYPE = scenegraph +PLUGIN_CLASS_NAME = QSGOpenVGAdaptation +load(qt_plugin) + +QMAKE_TARGET_PRODUCT = "Qt Quick OpenVG Renderer (Qt $$QT_VERSION)" +QMAKE_TARGET_DESCRIPTION = "Quick OpenVG Renderer for Qt." + +QMAKE_USE += openvg + +OTHER_FILES += $$PWD/openvg.json + +HEADERS += \ + qsgopenvgadaptation_p.h \ + qsgopenvgcontext_p.h \ + qsgopenvgrenderloop_p.h \ + qsgopenvgglyphnode_p.h \ + qopenvgcontext_p.h \ + qsgopenvgrenderer_p.h \ + qsgopenvginternalrectanglenode.h \ + qsgopenvgnodevisitor.h \ + qopenvgmatrix.h \ + qsgopenvgpublicnodes.h \ + qsgopenvginternalimagenode.h \ + qsgopenvgtexture.h \ + qsgopenvglayer.h \ + qsgopenvghelpers.h \ + qsgopenvgfontglyphcache.h \ + qsgopenvgpainternode.h \ + qsgopenvgspritenode.h \ + qsgopenvgrenderable.h + +SOURCES += \ + qsgopenvgadaptation.cpp \ + qsgopenvgcontext.cpp \ + qsgopenvgrenderloop.cpp \ + qsgopenvgglyphnode.cpp \ + qopenvgcontext.cpp \ + qsgopenvgrenderer.cpp \ + qsgopenvginternalrectanglenode.cpp \ + qsgopenvgnodevisitor.cpp \ + qopenvgmatrix.cpp \ + qsgopenvgpublicnodes.cpp \ + qsgopenvginternalimagenode.cpp \ + qsgopenvgtexture.cpp \ + qsgopenvglayer.cpp \ + qsgopenvghelpers.cpp \ + qsgopenvgfontglyphcache.cpp \ + qsgopenvgpainternode.cpp \ + qsgopenvgspritenode.cpp \ + qsgopenvgrenderable.cpp diff --git a/src/plugins/scenegraph/openvg/qopenvgcontext.cpp b/src/plugins/scenegraph/openvg/qopenvgcontext.cpp new file mode 100644 index 0000000000..ea2c24afdb --- /dev/null +++ b/src/plugins/scenegraph/openvg/qopenvgcontext.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qpa/qplatformnativeinterface.h> +#include <QtGui/QGuiApplication> +#include <QtCore/QVector> +#include <QtCore/QDebug> + +#include "qopenvgcontext_p.h" + +QT_BEGIN_NAMESPACE + +QOpenVGContext::QOpenVGContext(QWindow *window) + : m_window(window) +{ + QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); + m_display = reinterpret_cast<EGLDisplay>(nativeInterface->nativeResourceForWindow("EglDisplay", window)); + m_surface = reinterpret_cast<EGLSurface>(nativeInterface->nativeResourceForWindow("EglSurface", window)); + + if (m_display == 0) + qFatal("QOpenVGContext: failed to get EGLDisplay"); + if (m_surface == 0) + qFatal("QOpenVGContext: failed to get EGLSurface"); + + EGLint configID = 0; + if (eglQuerySurface(m_display, m_surface, EGL_CONFIG_ID, &configID)) { + EGLint numConfigs; + const EGLint configAttribs[] = { + EGL_CONFIG_ID, configID, + EGL_NONE + }; + eglChooseConfig(m_display, configAttribs, &m_config, 1, &numConfigs); + } else { + qFatal("QOpenVGContext: failed to get surface config"); + } + + // Create an EGL Context + eglBindAPI(EGL_OPENVG_API); + m_context = eglCreateContext(m_display, m_config, EGL_NO_CONTEXT, 0); + if (!m_context) + qFatal("QOpenVGContext: eglCreateContext failed"); +} + +QOpenVGContext::~QOpenVGContext() +{ + doneCurrent(); + eglDestroyContext(m_display, m_context); +} + +void QOpenVGContext::makeCurrent() +{ + makeCurrent(m_surface); +} + +void QOpenVGContext::makeCurrent(EGLSurface surface) +{ + eglMakeCurrent(m_display, surface, surface, m_context); +} + +void QOpenVGContext::doneCurrent() +{ + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +void QOpenVGContext::swapBuffers() +{ + swapBuffers(m_surface); +} + +void QOpenVGContext::swapBuffers(EGLSurface surface) +{ + eglSwapBuffers(m_display, surface); +} + +QWindow *QOpenVGContext::window() const +{ + return m_window; +} + +QImage QOpenVGContext::readFramebuffer(const QSize &size) +{ + QImage framebufferImage(size, QImage::Format_RGB32); + vgReadPixels(framebufferImage.bits(), framebufferImage.bytesPerLine(), VG_sXRGB_8888, 0, 0, size.width(), size.height()); + return framebufferImage.mirrored(false, true); +} + +void QOpenVGContext::getConfigs() +{ + EGLint configsAvailable = 0; + eglGetConfigs(m_display, 0, 0, &configsAvailable); + + QVector<EGLConfig> configs(configsAvailable); + eglGetConfigs(m_display, configs.data(), configs.size(), &configsAvailable); + + for (EGLConfig config : configs) { + EGLint value; + eglGetConfigAttrib(m_display, config, EGL_CONFIG_ID, &value); + qDebug() << "#################\n" << "EGL_CONFIG_ID:" << value; + eglGetConfigAttrib(m_display, config, EGL_BUFFER_SIZE, &value); + qDebug() << "EGL_BUFFER_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &value); + qDebug() << "EGL_ALPHA_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &value); + qDebug() << "EGL_RED_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &value); + qDebug() << "EGL_GREEN_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &value); + qDebug() << "EGL_BLUE_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_DEPTH_SIZE, &value); + qDebug() << "EGL_DEPTH_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_STENCIL_SIZE, &value); + qDebug() << "EGL_STENCIL_SIZE:" << value; + + eglGetConfigAttrib(m_display, config, EGL_ALPHA_MASK_SIZE, &value); + qDebug() << "EGL_ALPHA_MASK_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_BIND_TO_TEXTURE_RGB, &value); + qDebug() << "EGL_BIND_TO_TEXTURE_RGB:" << value; + eglGetConfigAttrib(m_display, config, EGL_BIND_TO_TEXTURE_RGBA, &value); + qDebug() << "EGL_BIND_TO_TEXTURE_RGBA:" << value; + + + eglGetConfigAttrib(m_display, config, EGL_COLOR_BUFFER_TYPE, &value); + qDebug() << "EGL_COLOR_BUFFER_TYPE:" << value; + eglGetConfigAttrib(m_display, config, EGL_CONFIG_CAVEAT, &value); + qDebug() << "EGL_CONFIG_CAVEAT:" << value; + eglGetConfigAttrib(m_display, config, EGL_CONFORMANT, &value); + qDebug() << "EGL_CONFORMANT:" << value; + + + eglGetConfigAttrib(m_display, config, EGL_LEVEL, &value); + qDebug() << "EGL_LEVEL:" << value; + eglGetConfigAttrib(m_display, config, EGL_LUMINANCE_SIZE, &value); + qDebug() << "EGL_LUMINANCE_SIZE:" << value; + eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_WIDTH, &value); + qDebug() << "EGL_MAX_PBUFFER_WIDTH:" << value; + eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_HEIGHT, &value); + qDebug() << "EGL_MAX_PBUFFER_HEIGHT:" << value; + eglGetConfigAttrib(m_display, config, EGL_MAX_PBUFFER_PIXELS, &value); + qDebug() << "EGL_MAX_PBUFFER_PIXELS:" << value; + eglGetConfigAttrib(m_display, config, EGL_MAX_SWAP_INTERVAL, &value); + qDebug() << "EGL_MAX_SWAP_INTERVAL:" << value; + eglGetConfigAttrib(m_display, config, EGL_MIN_SWAP_INTERVAL, &value); + qDebug() << "EGL_MIN_SWAP_INTERVAL:" << value; + eglGetConfigAttrib(m_display, config, EGL_NATIVE_RENDERABLE, &value); + qDebug() << "EGL_NATIVE_RENDERABLE:" << value; + eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &value); + qDebug() << "EGL_NATIVE_VISUAL_ID:" << value; + eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_TYPE, &value); + qDebug() << "EGL_NATIVE_VISUAL_TYPE:" << value; + eglGetConfigAttrib(m_display, config, EGL_RENDERABLE_TYPE, &value); + qDebug() << "EGL_RENDERABLE_TYPE:" << value; + eglGetConfigAttrib(m_display, config, EGL_SAMPLE_BUFFERS, &value); + qDebug() << "EGL_SAMPLE_BUFFERS:" << value; + eglGetConfigAttrib(m_display, config, EGL_SAMPLES, &value); + qDebug() << "EGL_SAMPLES:" << value; + + eglGetConfigAttrib(m_display, config, EGL_SURFACE_TYPE, &value); + qDebug() << "EGL_SURFACE_TYPE:" << value; + eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_TYPE, &value); + qDebug() << "EGL_TRANSPARENT_TYPE:" << value; + eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_RED_VALUE, &value); + qDebug() << "EGL_TRANSPARENT_RED_VALUE:" << value; + eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_GREEN_VALUE, &value); + qDebug() << "EGL_TRANSPARENT_GREEN_VALUE:" << value; + eglGetConfigAttrib(m_display, config, EGL_TRANSPARENT_BLUE_VALUE, &value); + qDebug() << "EGL_TRANSPARENT_BLUE_VALUE:" << value; + } +} + +void QOpenVGContext::checkErrors() +{ + VGErrorCode error; + EGLint eglError; + do { + error = vgGetError(); + eglError = eglGetError(); + qDebug() << "error: " << QString::number(error, 16); + qDebug() << "eglError: " << QString::number(eglError, 16); + } while (error != VG_NO_ERROR && eglError != EGL_SUCCESS); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qopenvgcontext_p.h b/src/plugins/scenegraph/openvg/qopenvgcontext_p.h new file mode 100644 index 0000000000..a1ba73957f --- /dev/null +++ b/src/plugins/scenegraph/openvg/qopenvgcontext_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOPENVGCONTEXT_H +#define QOPENVGCONTEXT_H + +#include <QtGui/QWindow> +#include <QtGui/QImage> + +#include <EGL/egl.h> +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QOpenVGContext +{ +public: + QOpenVGContext(QWindow *window); + ~QOpenVGContext(); + + void makeCurrent(); + void makeCurrent(EGLSurface surface); + void doneCurrent(); + void swapBuffers(); + void swapBuffers(EGLSurface surface); + + + QWindow *window() const; + + EGLDisplay eglDisplay() { return m_display; } + EGLConfig eglConfig() { return m_config; } + EGLContext eglContext() { return m_context; } + + QImage readFramebuffer(const QSize &size); + + void getConfigs(); + + static void checkErrors(); + +private: + EGLSurface m_surface; + EGLDisplay m_display; + EGLConfig m_config; + EGLContext m_context; + + QWindow *m_window; + +}; + +QT_END_NAMESPACE + +#endif // QOPENVGCONTEXT_H diff --git a/src/plugins/scenegraph/openvg/qopenvgmatrix.cpp b/src/plugins/scenegraph/openvg/qopenvgmatrix.cpp new file mode 100644 index 0000000000..e55de2ce0d --- /dev/null +++ b/src/plugins/scenegraph/openvg/qopenvgmatrix.cpp @@ -0,0 +1,325 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qopenvgmatrix.h" + +QT_BEGIN_NAMESPACE + +// QOpenVGMatrix: Because Qt will never have enough matrix classes +// Internally the data is stored as column-major format +// So this is a 3x3 version of QMatrix4x4 for optimal +// OpenVG usage. + +QOpenVGMatrix::QOpenVGMatrix() +{ + setToIdentity(); +} + +QOpenVGMatrix::QOpenVGMatrix(const float *values) +{ + for (int col = 0; col < 3; ++col) + for (int row = 0; row < 3; ++row) + m[col][row] = values[col * 3 + row]; +} + +const float &QOpenVGMatrix::operator()(int row, int column) const +{ + Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4); + return m[column][row]; +} + +float &QOpenVGMatrix::operator()(int row, int column) +{ + Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4); + return m[column][row]; +} + +bool QOpenVGMatrix::isIdentity() const +{ + if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f) + return false; + if ( m[1][0] != 0.0f || m[1][1] != 1.0f) + return false; + if (m[1][2] != 0.0f || m[2][0] != 0.0f) + return false; + if (m[2][1] != 0.0f || m[2][2] != 1.0f) + return false; + + return true; +} + +void QOpenVGMatrix::setToIdentity() +{ + m[0][0] = 1.0f; + m[0][1] = 0.0f; + m[0][2] = 0.0f; + m[1][0] = 0.0f; + m[1][1] = 1.0f; + m[1][2] = 0.0f; + m[2][0] = 0.0f; + m[2][1] = 0.0f; + m[2][2] = 1.0f; +} + +void QOpenVGMatrix::fill(float value) +{ + m[0][0] = value; + m[0][1] = value; + m[0][2] = value; + m[1][0] = value; + m[1][1] = value; + m[1][2] = value; + m[2][0] = value; + m[2][1] = value; + m[2][2] = value; +} + +QOpenVGMatrix QOpenVGMatrix::transposed() const +{ + QOpenVGMatrix result; + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) + result.m[col][row] = m[row][col]; + } + return result; +} + +QOpenVGMatrix &QOpenVGMatrix::operator+=(const QOpenVGMatrix &other) +{ + m[0][0] += other.m[0][0]; + m[0][1] += other.m[0][1]; + m[0][2] += other.m[0][2]; + m[1][0] += other.m[1][0]; + m[1][1] += other.m[1][1]; + m[1][2] += other.m[1][2]; + m[2][0] += other.m[2][0]; + m[2][1] += other.m[2][1]; + m[2][2] += other.m[2][2]; + return *this; +} + +QOpenVGMatrix &QOpenVGMatrix::operator-=(const QOpenVGMatrix &other) +{ + m[0][0] -= other.m[0][0]; + m[0][1] -= other.m[0][1]; + m[0][2] -= other.m[0][2]; + m[1][0] -= other.m[1][0]; + m[1][1] -= other.m[1][1]; + m[1][2] -= other.m[1][2]; + m[2][0] -= other.m[2][0]; + m[2][1] -= other.m[2][1]; + m[2][2] -= other.m[2][2]; + return *this; +} + +QOpenVGMatrix &QOpenVGMatrix::operator*=(const QOpenVGMatrix &other) +{ + float m0, m1; + m0 = m[0][0] * other.m[0][0] + + m[1][0] * other.m[0][1] + + m[2][0] * other.m[0][2]; + m1 = m[0][0] * other.m[1][0] + + m[1][0] * other.m[1][1] + + m[2][0] * other.m[1][2]; + m[2][0] = m[0][0] * other.m[2][0] + + m[1][0] * other.m[2][1] + + m[2][0] * other.m[2][2]; + m[0][0] = m0; + m[1][0] = m1; + + m0 = m[0][1] * other.m[0][0] + + m[1][1] * other.m[0][1] + + m[2][1] * other.m[0][2]; + m1 = m[0][1] * other.m[1][0] + + m[1][1] * other.m[1][1] + + m[2][1] * other.m[1][2]; + m[2][1] = m[0][1] * other.m[2][0] + + m[1][1] * other.m[2][1] + + m[2][1] * other.m[2][2]; + m[0][1] = m0; + m[1][1] = m1; + + m0 = m[0][2] * other.m[0][0] + + m[1][2] * other.m[0][1] + + m[2][2] * other.m[0][2]; + m1 = m[0][2] * other.m[1][0] + + m[1][2] * other.m[1][1] + + m[2][2] * other.m[1][2]; + m[2][2] = m[0][2] * other.m[2][0] + + m[1][2] * other.m[2][1] + + m[2][2] * other.m[2][2]; + m[0][2] = m0; + m[1][2] = m1; + return *this; +} + +QOpenVGMatrix &QOpenVGMatrix::operator*=(float factor) +{ + m[0][0] *= factor; + m[0][1] *= factor; + m[0][2] *= factor; + m[1][0] *= factor; + m[1][1] *= factor; + m[1][2] *= factor; + m[2][0] *= factor; + m[2][1] *= factor; + m[2][2] *= factor; + return *this; +} + +QOpenVGMatrix &QOpenVGMatrix::operator/=(float divisor) +{ + m[0][0] /= divisor; + m[0][1] /= divisor; + m[0][2] /= divisor; + m[1][0] /= divisor; + m[1][1] /= divisor; + m[1][2] /= divisor; + m[2][0] /= divisor; + m[2][1] /= divisor; + m[2][2] /= divisor; + return *this; +} + +bool QOpenVGMatrix::operator==(const QOpenVGMatrix &other) const +{ + return m[0][0] == other.m[0][0] && + m[0][1] == other.m[0][1] && + m[0][2] == other.m[0][2] && + m[1][0] == other.m[1][0] && + m[1][1] == other.m[1][1] && + m[1][2] == other.m[1][2] && + m[2][0] == other.m[2][0] && + m[2][1] == other.m[2][1] && + m[2][2] == other.m[2][2]; +} + +bool QOpenVGMatrix::operator!=(const QOpenVGMatrix &other) const +{ + return m[0][0] != other.m[0][0] || + m[0][1] != other.m[0][1] || + m[0][2] != other.m[0][2] || + m[1][0] != other.m[1][0] || + m[1][1] != other.m[1][1] || + m[1][2] != other.m[1][2] || + m[2][0] != other.m[2][0] || + m[2][1] != other.m[2][1] || + m[2][2] != other.m[2][2]; +} + +void QOpenVGMatrix::copyDataTo(float *values) const +{ + // Row-Major? + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 3; ++col) + values[row * 3 + col] = float(m[col][row]); + } +} + +QOpenVGMatrix operator*(const QOpenVGMatrix &m1, const QOpenVGMatrix &m2) +{ + QOpenVGMatrix matrix; + matrix.m[0][0] = m1.m[0][0] * m2.m[0][0] + + m1.m[1][0] * m2.m[0][1] + + m1.m[2][0] * m2.m[0][2]; + matrix.m[0][1] = m1.m[0][1] * m2.m[0][0] + + m1.m[1][1] * m2.m[0][1] + + m1.m[2][1] * m2.m[0][2]; + matrix.m[0][2] = m1.m[0][2] * m2.m[0][0] + + m1.m[1][2] * m2.m[0][1] + + m1.m[2][2] * m2.m[0][2]; + + matrix.m[1][0] = m1.m[0][0] * m2.m[1][0] + + m1.m[1][0] * m2.m[1][1] + + m1.m[2][0] * m2.m[1][2]; + matrix.m[1][1] = m1.m[0][1] * m2.m[1][0] + + m1.m[1][1] * m2.m[1][1] + + m1.m[2][1] * m2.m[1][2]; + matrix.m[1][2] = m1.m[0][2] * m2.m[1][0] + + m1.m[1][2] * m2.m[1][1] + + m1.m[2][2] * m2.m[1][2]; + + matrix.m[2][0] = m1.m[0][0] * m2.m[2][0] + + m1.m[1][0] * m2.m[2][1] + + m1.m[2][0] * m2.m[2][2]; + matrix.m[2][1] = m1.m[0][1] * m2.m[2][0] + + m1.m[1][1] * m2.m[2][1] + + m1.m[2][1] * m2.m[2][2]; + matrix.m[2][2] = m1.m[0][2] * m2.m[2][0] + + m1.m[1][2] * m2.m[2][1] + + m1.m[2][2] * m2.m[2][2]; + return matrix; +} + +QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m) +{ + QDebugStateSaver saver(dbg); + // Output in row-major order because it is more human-readable. + dbg.nospace() << "QOpenVGMatrix:(" << endl + << qSetFieldWidth(10) + << m(0, 0) << m(0, 1) << m(0, 2) << endl + << m(1, 0) << m(1, 1) << m(1, 2) << endl + << m(2, 0) << m(2, 1) << m(2, 2) << endl + << qSetFieldWidth(0) << ')'; + return dbg; +} + +QDataStream &operator<<(QDataStream &stream, const QOpenVGMatrix &matrix) +{ + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 3; ++col) + stream << matrix(row, col); + return stream; +} + + +QDataStream &operator>>(QDataStream &stream, QOpenVGMatrix &matrix) +{ + float x; + for (int row = 0; row < 4; ++row) { + for (int col = 0; col < 4; ++col) { + stream >> x; + matrix(row, col) = x; + } + } + return stream; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qopenvgmatrix.h b/src/plugins/scenegraph/openvg/qopenvgmatrix.h new file mode 100644 index 0000000000..644c9da5bc --- /dev/null +++ b/src/plugins/scenegraph/openvg/qopenvgmatrix.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QOPENVGMATRIX_H +#define QOPENVGMATRIX_H + +#include <QtCore/qdebug.h> +#include <QtCore/QDataStream> + +QT_BEGIN_NAMESPACE + +class QOpenVGMatrix +{ +public: + QOpenVGMatrix(); + explicit QOpenVGMatrix(const float *values); + + const float& operator()(int row, int column) const; + float& operator()(int row, int column); + + bool isIdentity() const; + void setToIdentity(); + + void fill(float value); + + QOpenVGMatrix transposed() const; + + QOpenVGMatrix& operator+=(const QOpenVGMatrix& other); + QOpenVGMatrix& operator-=(const QOpenVGMatrix& other); + QOpenVGMatrix& operator*=(const QOpenVGMatrix& other); + QOpenVGMatrix& operator*=(float factor); + QOpenVGMatrix& operator/=(float divisor); + friend QOpenVGMatrix operator*(const QOpenVGMatrix& m1, const QOpenVGMatrix& m2); +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m); +#endif + bool operator==(const QOpenVGMatrix& other) const; + bool operator!=(const QOpenVGMatrix& other) const; + + void copyDataTo(float *values) const; + + float *data() { return *m; } + const float *data() const { return *m; } + const float *constData() const { return *m; } + +private: + float m[3][3]; +}; + +QOpenVGMatrix operator*(const QOpenVGMatrix& m1, const QOpenVGMatrix& m2); + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QOpenVGMatrix &m); +#endif + +#ifndef QT_NO_DATASTREAM +QDataStream &operator<<(QDataStream &, const QOpenVGMatrix &); +QDataStream &operator>>(QDataStream &, QOpenVGMatrix &); +#endif + +QT_END_NAMESPACE + +#endif // QOPENVGMATRIX_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgadaptation.cpp b/src/plugins/scenegraph/openvg/qsgopenvgadaptation.cpp new file mode 100644 index 0000000000..1a26522459 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgadaptation.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgadaptation_p.h" + +#include "qsgopenvgcontext_p.h" +#include "qsgopenvgrenderloop_p.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGAdaptation::QSGOpenVGAdaptation(QObject *parent) + : QSGContextPlugin(parent) +{ +} + +QStringList QSGOpenVGAdaptation::keys() const +{ + return QStringList() << QLatin1String("openvg"); +} + +QSGContext *QSGOpenVGAdaptation::create(const QString &key) const +{ + Q_UNUSED(key) + if (!instance) + instance = new QSGOpenVGContext(); + return instance; +} + +QSGRenderLoop *QSGOpenVGAdaptation::createWindowManager() +{ + return new QSGOpenVGRenderLoop(); +} + +QSGContextFactoryInterface::Flags QSGOpenVGAdaptation::flags(const QString &key) const +{ + Q_UNUSED(key) + return 0; +} + +QSGOpenVGContext *QSGOpenVGAdaptation::instance = nullptr; + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgadaptation_p.h b/src/plugins/scenegraph/openvg/qsgopenvgadaptation_p.h new file mode 100644 index 0000000000..77f79af9ac --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgadaptation_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGADAPTATION_H +#define QSGOPENVGADAPTATION_H + +#include <private/qsgcontextplugin_p.h> + +QT_BEGIN_NAMESPACE + +class QSGContext; +class QSGRenderLoop; +class QSGOpenVGContext; + +class QSGOpenVGAdaptation : public QSGContextPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QSGContextFactoryInterface" FILE "openvg.json") +public: + QSGOpenVGAdaptation(QObject *parent = nullptr); + + QStringList keys() const override; + QSGContext *create(const QString &key) const override; + QSGRenderLoop *createWindowManager() override; + Flags flags(const QString &key) const override; +private: + static QSGOpenVGContext *instance; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGADAPTATION_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp new file mode 100644 index 0000000000..22a80c62e8 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgcontext.cpp @@ -0,0 +1,219 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgcontext_p.h" +#include "qsgopenvgrenderer_p.h" +#include "qsgopenvginternalrectanglenode.h" +#include "qsgopenvginternalimagenode.h" +#include "qsgopenvgpublicnodes.h" +#include "qsgopenvgtexture.h" +#include "qsgopenvglayer.h" +#include "qsgopenvgglyphnode_p.h" +#include "qsgopenvgfontglyphcache.h" +#include "qsgopenvgpainternode.h" +#include "qsgopenvgspritenode.h" + +#include "qopenvgcontext_p.h" + +#include <private/qsgrenderer_p.h> + +// polish, animations, sync, render and swap in the render loop +Q_LOGGING_CATEGORY(QSG_OPENVG_LOG_TIME_RENDERLOOP, "qt.scenegraph.time.renderloop") + +QT_BEGIN_NAMESPACE + +QSGOpenVGRenderContext::QSGOpenVGRenderContext(QSGContext *context) + : QSGRenderContext(context) + , m_vgContext(nullptr) + , m_glyphCacheManager(nullptr) +{ + +} + +void QSGOpenVGRenderContext::initialize(void *context) +{ + m_vgContext = static_cast<QOpenVGContext*>(context); + QSGRenderContext::initialize(context); +} + +void QSGOpenVGRenderContext::invalidate() +{ + m_vgContext = nullptr; + delete m_glyphCacheManager; + m_glyphCacheManager = nullptr; + QSGRenderContext::invalidate(); +} + +void QSGOpenVGRenderContext::renderNextFrame(QSGRenderer *renderer, uint fboId) +{ + renderer->renderScene(fboId); +} + +QSGTexture *QSGOpenVGRenderContext::createTexture(const QImage &image, uint flags) const +{ + QImage tmp = image; + + // Make sure image is not larger than maxTextureSize + int maxSize = maxTextureSize(); + if (tmp.width() > maxSize || tmp.height() > maxSize) { + tmp = tmp.scaled(qMin(maxSize, tmp.width()), qMin(maxSize, tmp.height()), Qt::IgnoreAspectRatio, Qt::FastTransformation); + } + + return new QSGOpenVGTexture(tmp, flags); +} + +QSGRenderer *QSGOpenVGRenderContext::createRenderer() +{ + return new QSGOpenVGRenderer(this); +} + +QSGOpenVGContext::QSGOpenVGContext(QObject *parent) +{ + Q_UNUSED(parent) +} + +QSGRenderContext *QSGOpenVGContext::createRenderContext() +{ + return new QSGOpenVGRenderContext(this); +} + +QSGRectangleNode *QSGOpenVGContext::createRectangleNode() +{ + return new QSGOpenVGRectangleNode; +} + +QSGImageNode *QSGOpenVGContext::createImageNode() +{ + return new QSGOpenVGImageNode; +} + +QSGPainterNode *QSGOpenVGContext::createPainterNode(QQuickPaintedItem *item) +{ + Q_UNUSED(item) + return new QSGOpenVGPainterNode(item); +} + +QSGGlyphNode *QSGOpenVGContext::createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) +{ + Q_UNUSED(preferNativeGlyphNode) + return new QSGOpenVGGlyphNode(rc); +} + +QSGNinePatchNode *QSGOpenVGContext::createNinePatchNode() +{ + return new QSGOpenVGNinePatchNode; +} + +QSGLayer *QSGOpenVGContext::createLayer(QSGRenderContext *renderContext) +{ + return new QSGOpenVGLayer(renderContext); +} + +QSurfaceFormat QSGOpenVGContext::defaultSurfaceFormat() const +{ + QSurfaceFormat format = QSurfaceFormat::defaultFormat(); + format.setRenderableType(QSurfaceFormat::OpenVG); + format.setMajorVersion(1); + return format; +} + +QSGInternalRectangleNode *QSGOpenVGContext::createInternalRectangleNode() +{ + return new QSGOpenVGInternalRectangleNode(); +} + +QSGInternalImageNode *QSGOpenVGContext::createInternalImageNode() +{ + return new QSGOpenVGInternalImageNode(); +} + +int QSGOpenVGRenderContext::maxTextureSize() const +{ + VGint width = vgGeti(VG_MAX_IMAGE_WIDTH); + VGint height = vgGeti(VG_MAX_IMAGE_HEIGHT); + + return qMin(width, height); +} + + +QSGSpriteNode *QSGOpenVGContext::createSpriteNode() +{ + return new QSGOpenVGSpriteNode(); +} + +QSGRendererInterface *QSGOpenVGContext::rendererInterface(QSGRenderContext *renderContext) +{ + return static_cast<QSGOpenVGRenderContext *>(renderContext); +} + +QSGRendererInterface::GraphicsApi QSGOpenVGRenderContext::graphicsApi() const +{ + return OpenVG; +} + +QSGRendererInterface::ShaderType QSGOpenVGRenderContext::shaderType() const +{ + return UnknownShadingLanguage; +} + +QSGRendererInterface::ShaderCompilationTypes QSGOpenVGRenderContext::shaderCompilationType() const +{ + return 0; +} + +QSGRendererInterface::ShaderSourceTypes QSGOpenVGRenderContext::shaderSourceType() const +{ + return 0; +} + +QSGOpenVGFontGlyphCache *QSGOpenVGRenderContext::glyphCache(const QRawFont &rawFont) +{ + if (!m_glyphCacheManager) + m_glyphCacheManager = new QSGOpenVGFontGlyphCacheManager; + + QSGOpenVGFontGlyphCache *cache = m_glyphCacheManager->cache(rawFont); + if (!cache) { + cache = new QSGOpenVGFontGlyphCache(m_glyphCacheManager, rawFont); + m_glyphCacheManager->insertCache(rawFont, cache); + } + + return cache; +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgcontext_p.h b/src/plugins/scenegraph/openvg/qsgopenvgcontext_p.h new file mode 100644 index 0000000000..fa9939a253 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgcontext_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGCONTEXT_H +#define QSGOPENVGCONTEXT_H + +#include <private/qsgcontext_p.h> +#include <qsgrendererinterface.h> + +Q_DECLARE_LOGGING_CATEGORY(QSG_OPENVG_LOG_TIME_RENDERLOOP) + +QT_BEGIN_NAMESPACE + +class QOpenVGContext; +class QSGOpenVGFontGlyphCache; +class QSGOpenVGFontGlyphCacheManager; + +class QSGOpenVGRenderContext : public QSGRenderContext, public QSGRendererInterface +{ + Q_OBJECT +public: + QSGOpenVGRenderContext(QSGContext *context); + + void initialize(void *context) override; + void invalidate() override; + void renderNextFrame(QSGRenderer *renderer, uint fboId) override; + QSGTexture *createTexture(const QImage &image, uint flags) const override; + QSGRenderer *createRenderer() override; + int maxTextureSize() const override; + + // QSGRendererInterface interface + GraphicsApi graphicsApi() const override; + ShaderType shaderType() const override; + ShaderCompilationTypes shaderCompilationType() const override; + ShaderSourceTypes shaderSourceType() const override; + + QOpenVGContext* vgContext() { return m_vgContext; } + QSGOpenVGFontGlyphCache* glyphCache(const QRawFont &rawFont); + +private: + QOpenVGContext *m_vgContext; + QSGOpenVGFontGlyphCacheManager *m_glyphCacheManager; + +}; + +class QSGOpenVGContext : public QSGContext +{ + Q_OBJECT +public: + QSGOpenVGContext(QObject *parent = nullptr); + + QSGRenderContext *createRenderContext() override; + QSGRectangleNode *createRectangleNode() override; + QSGImageNode *createImageNode() override; + QSGPainterNode *createPainterNode(QQuickPaintedItem *item) override; + QSGGlyphNode *createGlyphNode(QSGRenderContext *rc, bool preferNativeGlyphNode) override; + QSGNinePatchNode *createNinePatchNode() override; + QSGLayer *createLayer(QSGRenderContext *renderContext) override; + QSurfaceFormat defaultSurfaceFormat() const override; + QSGInternalRectangleNode *createInternalRectangleNode() override; + QSGInternalImageNode *createInternalImageNode() override; + QSGSpriteNode *createSpriteNode() override; + QSGRendererInterface *rendererInterface(QSGRenderContext *renderContext) override; +}; + +#endif // QSGOPENVGCONTEXT_H + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp new file mode 100644 index 0000000000..1ed54f7b6a --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgfontglyphcache.h" +#include "qsgopenvghelpers.h" +#include <private/qfontengine_p.h> +#include <private/qrawfont_p.h> + +QT_BEGIN_NAMESPACE + +QSGOpenVGFontGlyphCacheManager::QSGOpenVGFontGlyphCacheManager() +{ + +} + +QSGOpenVGFontGlyphCacheManager::~QSGOpenVGFontGlyphCacheManager() +{ + qDeleteAll(m_caches); +} + +QSGOpenVGFontGlyphCache *QSGOpenVGFontGlyphCacheManager::cache(const QRawFont &font) +{ + return m_caches.value(fontKey(font), nullptr); +} + +void QSGOpenVGFontGlyphCacheManager::insertCache(const QRawFont &font, QSGOpenVGFontGlyphCache *cache) +{ + m_caches.insert(fontKey(font), cache); +} + +QString QSGOpenVGFontGlyphCacheManager::fontKey(const QRawFont &font) +{ + QFontEngine *fe = QRawFontPrivate::get(font)->fontEngine; + if (!fe->faceId().filename.isEmpty()) { + QByteArray keyName = fe->faceId().filename; + if (font.style() != QFont::StyleNormal) + keyName += QByteArray(" I"); + if (font.weight() != QFont::Normal) + keyName += ' ' + QByteArray::number(font.weight()); + keyName += " " + QString::number(font.pixelSize()); + keyName += QByteArray(" DF"); + return QString::fromUtf8(keyName); + } else { + return QString::fromLatin1("%1_%2_%3_%4_%5") + .arg(font.familyName()) + .arg(font.styleName()) + .arg(font.weight()) + .arg(font.style()) + .arg(font.pixelSize()); + } +} + + +QSGOpenVGFontGlyphCache::QSGOpenVGFontGlyphCache(QSGOpenVGFontGlyphCacheManager *manager, const QRawFont &font) + : m_manager(manager) +{ + m_referenceFont = font; + QRawFontPrivate *fontD = QRawFontPrivate::get(font); + m_glyphCount = fontD->fontEngine->glyphCount(); + m_font = vgCreateFont(0); +} + +QSGOpenVGFontGlyphCache::~QSGOpenVGFontGlyphCache() +{ + if (m_font != VG_INVALID_HANDLE) + vgDestroyFont(m_font); +} + +void QSGOpenVGFontGlyphCache::populate(const QVector<quint32> &glyphs) +{ + QSet<quint32> referencedGlyphs; + QSet<quint32> newGlyphs; + int count = glyphs.count(); + for (int i = 0; i < count; ++i) { + quint32 glyphIndex = glyphs.at(i); + if ((int) glyphIndex >= glyphCount()) { + qWarning("Warning: glyph is not available with index %d", glyphIndex); + continue; + } + + referencedGlyphs.insert(glyphIndex); + + + if (!m_cachedGlyphs.contains(glyphIndex)) { + newGlyphs.insert(glyphIndex); + } + } + + referenceGlyphs(referencedGlyphs); + if (!newGlyphs.isEmpty()) + requestGlyphs(newGlyphs); +} + +void QSGOpenVGFontGlyphCache::release(const QVector<quint32> &glyphs) +{ + QSet<quint32> unusedGlyphs; + int count = glyphs.count(); + for (int i = 0; i < count; ++i) { + quint32 glyphIndex = glyphs.at(i); + unusedGlyphs.insert(glyphIndex); + } + releaseGlyphs(unusedGlyphs); +} + +void QSGOpenVGFontGlyphCache::requestGlyphs(const QSet<quint32> &glyphs) +{ + VGfloat origin[2]; + VGfloat escapement[2]; + QRectF metrics; + QRawFont rawFont = m_referenceFont; + + // Before adding any new glyphs, remove any unused glyphs + for (auto glyph : qAsConst(m_unusedGlyphs)) { + vgClearGlyph(m_font, glyph); + } + + for (auto glyph : glyphs) { + m_cachedGlyphs.insert(glyph); + + // Calculate the path for the glyph and cache it. + QPainterPath path = rawFont.pathForGlyph(glyph); + VGPath vgPath; + if (!path.isEmpty()) { + vgPath = QSGOpenVGHelpers::qPainterPathToVGPath(path); + } else { + // Probably a "space" character with no visible outline. + vgPath = VG_INVALID_HANDLE; + } + origin[0] = 0; + origin[1] = 0; + escapement[0] = 0; + escapement[1] = 0; + vgSetGlyphToPath(m_font, glyph, vgPath, VG_FALSE, origin, escapement); + vgDestroyPath(vgPath); // Reduce reference count. + } + +} + +void QSGOpenVGFontGlyphCache::referenceGlyphs(const QSet<quint32> &glyphs) +{ + m_unusedGlyphs -= glyphs; +} + +void QSGOpenVGFontGlyphCache::releaseGlyphs(const QSet<quint32> &glyphs) +{ + m_unusedGlyphs += glyphs; +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h new file mode 100644 index 0000000000..a4a51cd2b6 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGFONTGLYPHCACHE_H +#define QSGOPENVGFONTGLYPHCACHE_H + +#include <QtGui/QGlyphRun> +#include <QtCore/QSet> +#include <QtCore/QLinkedList> +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGFontGlyphCache; + +class QSGOpenVGFontGlyphCacheManager +{ +public: + QSGOpenVGFontGlyphCacheManager(); + ~QSGOpenVGFontGlyphCacheManager(); + + QSGOpenVGFontGlyphCache *cache(const QRawFont &font); + void insertCache(const QRawFont &font, QSGOpenVGFontGlyphCache *cache); + +private: + static QString fontKey(const QRawFont &font); + + QHash<QString, QSGOpenVGFontGlyphCache *> m_caches; +}; + +class QSGOpenVGFontGlyphCache +{ +public: + QSGOpenVGFontGlyphCache(QSGOpenVGFontGlyphCacheManager *manager, const QRawFont &font); + ~QSGOpenVGFontGlyphCache(); + + const QSGOpenVGFontGlyphCacheManager *manager() const { return m_manager; } + const QRawFont &referenceFont() const { return m_referenceFont; } + int glyphCount() const { return m_glyphCount; } + + void populate(const QVector<quint32> &glyphs); + void release(const QVector<quint32> &glyphs); + + VGFont font() { return m_font; } + +private: + void requestGlyphs(const QSet<quint32> &glyphs); + void referenceGlyphs(const QSet<quint32> &glyphs); + void releaseGlyphs(const QSet<quint32> &glyphs); + + QSGOpenVGFontGlyphCacheManager *m_manager; + QRawFont m_referenceFont; + int m_glyphCount; + + VGFont m_font; + QSet<quint32> m_cachedGlyphs; + QSet<quint32> m_unusedGlyphs; +}; + + +QT_END_NAMESPACE + +#endif // QSGOPENVGFONTGLYPHCACHE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgglyphnode.cpp b/src/plugins/scenegraph/openvg/qsgopenvgglyphnode.cpp new file mode 100644 index 0000000000..c90f0f0bbe --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgglyphnode.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgglyphnode_p.h" +#include "qopenvgcontext_p.h" +#include "qsgopenvgcontext_p.h" +#include "qsgopenvghelpers.h" +#include "qsgopenvgfontglyphcache.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGGlyphNode::QSGOpenVGGlyphNode(QSGRenderContext *rc) + : m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 0) + , m_style(QQuickText::Normal) + , m_glyphCache(nullptr) +{ + // Set Dummy material to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry(&m_geometry); + m_fontColorPaint = vgCreatePaint(); + m_styleColorPaint = vgCreatePaint(); + + // Get handle to Glyph Cache + m_renderContext = static_cast<QSGOpenVGRenderContext*>(rc); +} + +QSGOpenVGGlyphNode::~QSGOpenVGGlyphNode() +{ + if (m_glyphCache) + m_glyphCache->release(m_glyphRun.glyphIndexes()); + + vgDestroyPaint(m_fontColorPaint); + vgDestroyPaint(m_styleColorPaint); +} + +void QSGOpenVGGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs) +{ + // Obtain glyph cache for font + auto oldGlyphCache = m_glyphCache; + m_glyphCache = m_renderContext->glyphCache(glyphs.rawFont()); + if (m_glyphCache != oldGlyphCache) { + if (oldGlyphCache) + oldGlyphCache->release(m_glyphRun.glyphIndexes()); + } + m_glyphCache->populate(glyphs.glyphIndexes()); + + m_position = position; + m_glyphRun = glyphs; + + // Recreate ajustments + m_xAdjustments.clear(); + m_yAdjustments.clear(); + + for (int i = 1; i < glyphs.positions().count(); ++i) { + m_xAdjustments.append(glyphs.positions().at(i).x() - glyphs.positions().at(i-1).x()); + m_yAdjustments.append(glyphs.positions().at(i).y() - glyphs.positions().at(i-1).y()); + } +} + +void QSGOpenVGGlyphNode::setColor(const QColor &color) +{ + m_color = color; + vgSetParameteri(m_fontColorPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(m_fontColorPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_color, opacity()).constData()); +} + +void QSGOpenVGGlyphNode::setStyle(QQuickText::TextStyle style) +{ + m_style = style; +} + +void QSGOpenVGGlyphNode::setStyleColor(const QColor &color) +{ + m_styleColor = color; + vgSetParameteri(m_styleColorPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(m_styleColorPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_styleColor, opacity()).constData()); +} + +QPointF QSGOpenVGGlyphNode::baseLine() const +{ + return QPointF(); +} + +void QSGOpenVGGlyphNode::setPreferredAntialiasingMode(QSGGlyphNode::AntialiasingMode) +{ +} + +void QSGOpenVGGlyphNode::update() +{ +} + +void QSGOpenVGGlyphNode::render() +{ + if (m_glyphRun.positions().count() == 0) + return; + + // Rendering Style + qreal offset = 1.0; + + vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_BETTER); + + switch (m_style) { + case QQuickText::Normal: break; + case QQuickText::Outline: + // Set the correct fill state + vgSetPaint(m_styleColorPaint, VG_FILL_PATH); + drawGlyphsAtOffset(QPointF(0, offset)); + drawGlyphsAtOffset(QPointF(0, -offset)); + drawGlyphsAtOffset(QPointF(offset, 0)); + drawGlyphsAtOffset(QPointF(-offset, 0)); + break; + case QQuickText::Raised: + vgSetPaint(m_styleColorPaint, VG_FILL_PATH); + drawGlyphsAtOffset(QPointF(0, offset)); + break; + case QQuickText::Sunken: + vgSetPaint(m_styleColorPaint, VG_FILL_PATH); + drawGlyphsAtOffset(QPointF(0, -offset)); + break; + } + + // Set the correct fill state + vgSetPaint(m_fontColorPaint, VG_FILL_PATH); + drawGlyphsAtOffset(QPointF(0.0, 0.0)); + +} + +void QSGOpenVGGlyphNode::setOpacity(float opacity) +{ + if (QSGOpenVGRenderable::opacity() != opacity) { + QSGOpenVGRenderable::setOpacity(opacity); + // Update Colors + setColor(m_color); + setStyleColor(m_styleColor); + } +} + +void QSGOpenVGGlyphNode::drawGlyphsAtOffset(const QPointF &offset) +{ + QPointF firstPosition = m_glyphRun.positions()[0] + (m_position - QPointF(0, m_glyphRun.rawFont().ascent())); + VGfloat origin[2]; + origin[0] = firstPosition.x() + offset.x(); + origin[1] = firstPosition.y() + offset.y(); + vgSetfv(VG_GLYPH_ORIGIN, 2, origin); + + vgDrawGlyphs(m_glyphCache->font(), + m_glyphRun.glyphIndexes().count(), + (VGuint*)m_glyphRun.glyphIndexes().constData(), + m_xAdjustments.constData(), + m_yAdjustments.constData(), + VG_FILL_PATH, + VG_TRUE); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgglyphnode_p.h b/src/plugins/scenegraph/openvg/qsgopenvgglyphnode_p.h new file mode 100644 index 0000000000..205e3dcbc8 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgglyphnode_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGGLYPHNODE_H +#define QSGOPENVGGLYPHNODE_H + +#include <private/qsgadaptationlayer_p.h> +#include <QtCore/QVector> + +#include <VG/openvg.h> + +#include "qsgopenvgrenderable.h" +#include "qsgopenvgfontglyphcache.h" + +QT_BEGIN_NAMESPACE + +class QSGOpenVGFontGlyphCache; +class QSGOpenVGRenderContext; +class QSGRenderContext; + +class QSGOpenVGGlyphNode : public QSGGlyphNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGGlyphNode(QSGRenderContext *rc); + ~QSGOpenVGGlyphNode(); + + void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override; + void setColor(const QColor &color) override; + void setStyle(QQuickText::TextStyle style) override; + void setStyleColor(const QColor &color) override; + QPointF baseLine() const override; + void setPreferredAntialiasingMode(AntialiasingMode) override; + void update() override; + + void render() override; + void setOpacity(float opacity) override; + +private: + void drawGlyphsAtOffset(const QPointF &offset); + + QPointF m_position; + QGlyphRun m_glyphRun; + QColor m_color; + QSGGeometry m_geometry; + QQuickText::TextStyle m_style; + QColor m_styleColor; + + QSGOpenVGFontGlyphCache *m_glyphCache; + QVector<VGfloat> m_xAdjustments; + QVector<VGfloat> m_yAdjustments; + VGPaint m_fontColorPaint; + VGPaint m_styleColorPaint; + + QSGOpenVGRenderContext *m_renderContext; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGGLYPHNODE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvghelpers.cpp b/src/plugins/scenegraph/openvg/qsgopenvghelpers.cpp new file mode 100644 index 0000000000..6bc99d32a1 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvghelpers.cpp @@ -0,0 +1,433 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvghelpers.h" +#include <cmath> + +QT_BEGIN_NAMESPACE + +namespace QSGOpenVGHelpers { + +VGPath qPainterPathToVGPath(const QPainterPath &path) +{ + int count = path.elementCount(); + + VGPath vgpath = vgCreatePath(VG_PATH_FORMAT_STANDARD, + VG_PATH_DATATYPE_F, + 1.0f, // scale + 0.0f, // bias + count + 1, // segmentCapacityHint + count * 2, // coordCapacityHint + VG_PATH_CAPABILITY_ALL); + + if (count == 0) + return vgpath; + + QVector<VGfloat> coords; + QVector<VGubyte> segments; + + int curvePos = 0; + QPointF temp; + + // Keep track of the start and end of each sub-path. QPainterPath + // does not have an "implicit close" flag like QVectorPath does. + // We therefore have to detect closed paths by looking for a LineTo + // element that connects back to the initial MoveTo element. + qreal startx = 0.0; + qreal starty = 0.0; + qreal endx = 0.0; + qreal endy = 0.0; + bool haveStart = false; + bool haveEnd = false; + + for (int i = 0; i < count; ++i) { + const QPainterPath::Element element = path.elementAt(i); + switch (element.type) { + + case QPainterPath::MoveToElement: + { + if (haveStart && haveEnd && startx == endx && starty == endy) { + // Implicitly close the previous sub-path. + segments.append(VG_CLOSE_PATH); + } + temp = QPointF(element.x, element.y); + startx = temp.x(); + starty = temp.y(); + coords.append(startx); + coords.append(starty); + haveStart = true; + haveEnd = false; + segments.append(VG_MOVE_TO_ABS); + } + break; + + case QPainterPath::LineToElement: + { + temp = QPointF(element.x, element.y); + endx = temp.x(); + endy = temp.y(); + coords.append(endx); + coords.append(endy); + haveEnd = true; + segments.append(VG_LINE_TO_ABS); + } + break; + + case QPainterPath::CurveToElement: + { + temp = QPointF(element.x, element.y); + coords.append(temp.x()); + coords.append(temp.y()); + haveEnd = false; + curvePos = 2; + } + break; + + case QPainterPath::CurveToDataElement: + { + temp = QPointF(element.x, element.y); + coords.append(temp.x()); + coords.append(temp.y()); + haveEnd = false; + curvePos += 2; + if (curvePos == 6) { + curvePos = 0; + segments.append(VG_CUBIC_TO_ABS); + } + } + break; + + } + } + + if (haveStart && haveEnd && startx == endx && starty == endy) { + // Implicitly close the last sub-path. + segments.append(VG_CLOSE_PATH); + } + + vgAppendPathData(vgpath, segments.count(), + segments.constData(), coords.constData()); + + return vgpath; +} + + +void qDrawTiled(VGImage image, const QSize imageSize, const QRectF &targetRect, const QPointF offset, float scaleX, float scaleY) { + + //Check for valid image size and targetRect + if (imageSize.width() <= 0 || imageSize.height() <= 0) + return; + if (targetRect.width() <= 0 || targetRect.height() <= 0) + return; + + // This logic is mostly from the Qt Raster PaintEngine's qt_draw_tile + qreal drawH; + qreal drawW; + qreal xPos; + qreal xOff; + qreal yPos = targetRect.y(); + qreal yOff; + + if (offset.y() < 0) + yOff = imageSize.height() - qRound(-offset.y()) % imageSize.height(); + else + yOff = qRound(offset.y()) % imageSize.height(); + + + // Save the current image transform matrix + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + QVector<float> originalMatrix(9); + vgGetMatrix(originalMatrix.data()); + + while (!qFuzzyCompare(yPos, targetRect.y() + targetRect.height()) && + yPos < targetRect.y() + targetRect.height()) { + drawH = imageSize.height() - yOff; // Cropping first row + if (yPos + drawH * scaleY > targetRect.y() + targetRect.height()) { // Cropping last row + // Check that values aren't equal + if (!qFuzzyCompare((float)(yPos + drawH * scaleY), (float)(targetRect.y() + targetRect.height()))) + drawH = targetRect.y() + targetRect.height() - yPos; + } + xPos = targetRect.x(); + if (offset.x() < 0) + xOff = imageSize.width() - qRound(-offset.x()) % imageSize.width(); + else + xOff = qRound(offset.x()) % imageSize.width(); + + while (!qFuzzyCompare(xPos, targetRect.x() + targetRect.width()) && + xPos < targetRect.x() + targetRect.width()) { + drawW = imageSize.width() - xOff; // Cropping first column + if (xPos + drawW * scaleX > targetRect.x() + targetRect.width()) { + // Check that values aren't equal + if (!qFuzzyCompare((float)(xPos + drawW * scaleX), (float)(targetRect.x() + targetRect.width()))) + drawW = targetRect.x() + targetRect.width() - xPos; + } + if (round(drawW) > 0 && round(drawH) > 0) { // Can't source image less than 1 width or height + //Draw here + VGImage childRectImage = vgChildImage(image, xOff, yOff, round(drawW), round(drawH)); + vgTranslate(xPos, yPos); + vgScale(scaleX, scaleY); + vgDrawImage(childRectImage); + vgDestroyImage(childRectImage); + vgLoadMatrix(originalMatrix.constData()); + } + if ( drawW > 0) + xPos += drawW * scaleX; + xOff = 0; + } + if ( drawH > 0) + yPos += drawH * scaleY; + yOff = 0; + + } +} + +void qDrawBorderImage(VGImage image, const QSizeF &textureSize, const QRectF &targetRect, const QRectF &innerTargetRect, const QRectF &subSourceRect) +{ + // Create normalized margins + QMarginsF margins(qMax(innerTargetRect.left() - targetRect.left(), 0.0), + qMax(innerTargetRect.top() - targetRect.top(), 0.0), + qMax(targetRect.right() - innerTargetRect.right(), 0.0), + qMax(targetRect.bottom() - innerTargetRect.bottom(), 0.0)); + + QRectF sourceRect(0, 0, textureSize.width(), textureSize.height()); + + // Create all the subRects + QRectF topLeftSourceRect(sourceRect.topLeft(), QSizeF(margins.left(), margins.top())); + QRectF topRightSourceRect(sourceRect.width() - margins.right(), sourceRect.top(), margins.right(), margins.top()); + QRectF bottomLeftSourceRect(sourceRect.left(), sourceRect.height() - margins.bottom(), margins.left(), margins.bottom()); + QRectF bottomRightSourceRect(sourceRect.width() - margins.right(), sourceRect.height() - margins.bottom(), margins.right(), margins.bottom()); + + QRectF topSourceRect(margins.left(), 0.0, sourceRect.width() - (margins.right() + margins.left()), margins.top()); + QRectF topTargetRect(margins.left(), 0.0, innerTargetRect.width(), margins.top()); + QRectF bottomSourceRect(margins.left(), sourceRect.height() - margins.bottom(), sourceRect.width() - (margins.right() + margins.left()), margins.bottom()); + QRectF bottomTargetRect(margins.left(), targetRect.height() - margins.bottom(), innerTargetRect.width(), margins.bottom()); + QRectF leftSourceRect(0.0, margins.top(), margins.left(), sourceRect.height() - (margins.bottom() + margins.top())); + QRectF leftTargetRect(0.0, margins.top(), margins.left(), innerTargetRect.height()); + QRectF rightSourceRect(sourceRect.width() - margins.right(), margins.top(), margins.right(), sourceRect.height() - (margins.bottom() + margins.top())); + QRectF rightTargetRect(targetRect.width() - margins.right(), margins.top(), margins.right(), innerTargetRect.height()); + + QRectF centerSourceRect(margins.left(), margins.top(), sourceRect.width() - (margins.right() + margins.left()), sourceRect.height() - (margins.top() + margins.bottom())); + + // Draw the 9 different sections + // (1) Top Left (unscaled) + qDrawSubImage(image, + topLeftSourceRect, + targetRect.topLeft()); + + // (3) Top Right (unscaled) + qDrawSubImage(image, + topRightSourceRect, + QPointF(targetRect.width() - margins.right(), 0.0)); + + // (7) Bottom Left (unscaled) + qDrawSubImage(image, + bottomLeftSourceRect, + QPointF(targetRect.left(), targetRect.height() - margins.bottom())); + + // (9) Bottom Right (unscaled) + qDrawSubImage(image, + bottomRightSourceRect, + QPointF(targetRect.width() - margins.right(), targetRect.height() - margins.bottom())); + + double scaledWidth = 1.0; + double scaledHeight = 1.0; + + // (2) Top (scaled via horizontalTileRule) + VGImage topImage = vgChildImage(image, topSourceRect.x(), topSourceRect.y(), topSourceRect.width(), topSourceRect.height()); + scaledWidth = (topTargetRect.width() / subSourceRect.width()) / topSourceRect.width(); + + QSGOpenVGHelpers::qDrawTiled(topImage, topSourceRect.size().toSize(), topTargetRect, QPoint(0.0, 0.0), scaledWidth, 1); + + vgDestroyImage(topImage); + + // (8) Bottom (scaled via horizontalTileRule) + VGImage bottomImage = vgChildImage(image, bottomSourceRect.x(), bottomSourceRect.y(), bottomSourceRect.width(), bottomSourceRect.height()); + scaledWidth = (bottomTargetRect.width() / subSourceRect.width()) / bottomSourceRect.width(); + + QSGOpenVGHelpers::qDrawTiled(bottomImage, bottomSourceRect.size().toSize(), bottomTargetRect, QPoint(0.0, 0.0), scaledWidth, 1); + + vgDestroyImage(bottomImage); + + // (4) Left (scaled via verticalTileRule) + VGImage leftImage = vgChildImage(image, leftSourceRect.x(), leftSourceRect.y(), leftSourceRect.width(), leftSourceRect.height()); + scaledHeight = (leftTargetRect.height() / subSourceRect.height()) / leftSourceRect.height(); + QSGOpenVGHelpers::qDrawTiled(leftImage, leftSourceRect.size().toSize(), leftTargetRect, QPointF(0.0, 0.0), 1, scaledHeight); + + vgDestroyImage(leftImage); + + // (6) Right (scaled via verticalTileRule) + VGImage rightImage = vgChildImage(image, rightSourceRect.x(), rightSourceRect.y(), rightSourceRect.width(), rightSourceRect.height()); + scaledHeight = (rightTargetRect.height() / subSourceRect.height()) / rightSourceRect.height(); + + QSGOpenVGHelpers::qDrawTiled(rightImage, rightSourceRect.size().toSize(), rightTargetRect, QPointF(0, 0), 1, scaledHeight); + + vgDestroyImage(rightImage); + + // (5) Center (saled via verticalTileRule and horizontalTileRule) + VGImage centerImage = vgChildImage(image, centerSourceRect.x(), centerSourceRect.y(), centerSourceRect.width(), centerSourceRect.height()); + + scaledWidth = (innerTargetRect.width() / subSourceRect.width()) / centerSourceRect.width(); + scaledHeight = (innerTargetRect.height() / subSourceRect.height()) / centerSourceRect.height(); + + QSGOpenVGHelpers::qDrawTiled(centerImage, centerSourceRect.size().toSize(), innerTargetRect, QPointF(0, 0), scaledWidth, scaledHeight); + + vgDestroyImage(centerImage); +} + +void qDrawSubImage(VGImage image, const QRectF &sourceRect, const QPointF &destOffset) +{ + // Check for valid source size + if (sourceRect.width() <= 0 || sourceRect.height() <= 0) + return; + + // Save the current image transform matrix + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + QVector<float> originalMatrix(9); + vgGetMatrix(originalMatrix.data()); + + // Get the child Image + VGImage childRectImage = vgChildImage(image, sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height()); + vgTranslate(destOffset.x(), destOffset.y()); + vgDrawImage(childRectImage); + vgDestroyImage(childRectImage); + + // Pop Matrix + vgLoadMatrix(originalMatrix.constData()); +} + +const QVector<VGfloat> qColorToVGColor(const QColor &color, float opacity) +{ + QVector<VGfloat> vgColor(4); + vgColor[0] = color.redF(); + vgColor[1] = color.greenF(); + vgColor[2] = color.blueF(); + vgColor[3] = color.alphaF() * opacity; + return vgColor; +} + +VGImageFormat qImageFormatToVGImageFormat(QImage::Format format) +{ + VGImageFormat vgFormat; + + switch (format) { + case QImage::Format_Mono: + case QImage::Format_MonoLSB: + vgFormat = VG_BW_1; + break; + case QImage::Format_RGB32: + vgFormat = VG_sXRGB_8888; + break; + case QImage::Format_ARGB32: + vgFormat = VG_sARGB_8888; + break; + case QImage::Format_ARGB32_Premultiplied: + vgFormat = VG_sARGB_8888_PRE; + break; + case QImage::Format_RGB16: + vgFormat = VG_sRGB_565; + break; + case QImage::Format_RGBX8888: + vgFormat = VG_sRGBX_8888; + break; + case QImage::Format_RGBA8888: + vgFormat = VG_sRGBA_8888; + break; + case QImage::Format_RGBA8888_Premultiplied: + vgFormat = VG_sRGBA_8888_PRE; + break; + case QImage::Format_Alpha8: + vgFormat = VG_A_8; + break; + case QImage::Format_Grayscale8: + vgFormat = VG_sL_8; + break; + default: + //Invalid + vgFormat = (VGImageFormat)-1; + break; + } + + return vgFormat; +} + +QImage::Format qVGImageFormatToQImageFormat(VGImageFormat format) +{ + QImage::Format qImageFormat; + + switch (format) { + case VG_BW_1: + qImageFormat = QImage::Format_Mono; + break; + case VG_sXRGB_8888: + qImageFormat = QImage::Format_RGB32; + break; + case VG_sARGB_8888: + qImageFormat = QImage::Format_ARGB32; + break; + case VG_sARGB_8888_PRE: + qImageFormat = QImage::Format_ARGB32_Premultiplied; + break; + case VG_sRGB_565: + qImageFormat = QImage::Format_RGB16; + break; + case VG_sRGBX_8888: + qImageFormat = QImage::Format_RGBX8888; + break; + case VG_sRGBA_8888: + qImageFormat = QImage::Format_RGBA8888; + break; + case VG_sRGBA_8888_PRE: + qImageFormat = QImage::Format_RGBA8888_Premultiplied; + break; + case VG_A_8: + qImageFormat = QImage::Format_Alpha8; + break; + case VG_sL_8: + qImageFormat = QImage::Format_Grayscale8; + default: + qImageFormat = QImage::Format_ARGB32; + break; + } + + return qImageFormat; +} + +} // end namespace QSGOpenVGHelpers + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvghelpers.h b/src/plugins/scenegraph/openvg/qsgopenvghelpers.h new file mode 100644 index 0000000000..ee8ff73ca8 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvghelpers.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGHELPERS_H +#define QSGOPENVGHELPERS_H + +#include <QtGui/QPainterPath> +#include <QtGui/QColor> +#include <QtGui/QImage> +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +namespace QSGOpenVGHelpers { + +VGPath qPainterPathToVGPath(const QPainterPath &path); +void qDrawTiled(VGImage image, const QSize imageSize, const QRectF &targetRect, const QPointF offset, float scaleX, float scaleY); +void qDrawBorderImage(VGImage image, const QSizeF &textureSize, const QRectF &targetRect, const QRectF &innerTargetRect, const QRectF &subSourceRect); +void qDrawSubImage(VGImage image, const QRectF &sourceRect, const QPointF &destOffset); +const QVector<VGfloat> qColorToVGColor(const QColor &color, float opacity = 1.0f); +VGImageFormat qImageFormatToVGImageFormat(QImage::Format format); +QImage::Format qVGImageFormatToQImageFormat(VGImageFormat format); + +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGHELPERS_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp new file mode 100644 index 0000000000..2ab477f116 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvginternalimagenode.h" +#include "qsgopenvghelpers.h" + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +QSGOpenVGInternalImageNode::QSGOpenVGInternalImageNode() +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +QSGOpenVGInternalImageNode::~QSGOpenVGInternalImageNode() +{ + if (m_subSourceRectImage != 0) + vgDestroyImage(m_subSourceRectImage); +} + +void QSGOpenVGInternalImageNode::render() +{ + if (!m_texture) { + return; + } + + // Set Draw Mode + if (opacity() < 1.0) { + //Transparent + vgSetPaint(opacityPaint(), VG_FILL_PATH); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); + } else { + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + } + + + VGImage image = static_cast<VGImage>(m_texture->textureId()); + QSize textureSize = m_texture->textureSize(); + + + // If Mirrored + if (m_mirror) { + vgTranslate(m_targetRect.width(), 0.0f); + vgScale(-1.0, 1.0); + } + + if (m_smooth) + vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER); + else + vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED); + + + if (m_innerTargetRect != m_targetRect) { + // border image + QSGOpenVGHelpers::qDrawBorderImage(image, textureSize, m_targetRect, m_innerTargetRect, m_subSourceRect); + } else if (m_tileHorizontal || m_tileVertical) { + // Tilled Image + + float sx = m_targetRect.width() / (m_subSourceRect.width() * textureSize.width()); + float sy = m_targetRect.height() / (m_subSourceRect.height() * textureSize.height()); + QPointF offset(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height()); + + QSGOpenVGHelpers::qDrawTiled(image, textureSize, m_targetRect, offset, sx, sy); + + } else { + // Regular BLIT + + QRectF sr(m_subSourceRect.left() * textureSize.width(), m_subSourceRect.top() * textureSize.height(), + m_subSourceRect.width() * textureSize.width(), m_subSourceRect.height() * textureSize.height()); + + if (m_subSourceRectImageDirty) { + if (m_subSourceRectImage != 0) + vgDestroyImage(m_subSourceRectImage); + m_subSourceRectImage = vgChildImage(image, sr.x(), sr.y(), sr.width(), sr.height()); + m_subSourceRectImageDirty = false; + } + + // If the the source rect is the same as the target rect + if (sr == m_targetRect) { + vgDrawImage(image); + } else { + // Scale + float scaleX = m_targetRect.width() / sr.width(); + float scaleY = m_targetRect.height() / sr.height(); + vgTranslate(m_targetRect.x(), m_targetRect.y()); + vgScale(scaleX, scaleY); + vgDrawImage(m_subSourceRectImage); + } + } +} + +void QSGOpenVGInternalImageNode::setTargetRect(const QRectF &rect) +{ + if (rect == m_targetRect) + return; + m_targetRect = rect; + markDirty(DirtyGeometry); +} + +void QSGOpenVGInternalImageNode::setInnerTargetRect(const QRectF &rect) +{ + if (rect == m_innerTargetRect) + return; + m_innerTargetRect = rect; + markDirty(DirtyGeometry); +} + +void QSGOpenVGInternalImageNode::setInnerSourceRect(const QRectF &rect) +{ + if (rect == m_innerSourceRect) + return; + m_innerSourceRect = rect; + markDirty(DirtyGeometry); +} + +void QSGOpenVGInternalImageNode::setSubSourceRect(const QRectF &rect) +{ + if (rect == m_subSourceRect) + return; + m_subSourceRect = rect; + m_subSourceRectImageDirty = true; + markDirty(DirtyGeometry); +} + +void QSGOpenVGInternalImageNode::setTexture(QSGTexture *texture) +{ + m_texture = texture; + m_subSourceRectImageDirty = true; + markDirty(DirtyMaterial); +} + +void QSGOpenVGInternalImageNode::setMirror(bool mirror) +{ + if (m_mirror != mirror) { + m_mirror = mirror; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGInternalImageNode::setMipmapFiltering(QSGTexture::Filtering) +{ +} + +void QSGOpenVGInternalImageNode::setFiltering(QSGTexture::Filtering filtering) +{ + bool smooth = (filtering == QSGTexture::Linear); + if (smooth == m_smooth) + return; + + m_smooth = smooth; + markDirty(DirtyMaterial); +} + +void QSGOpenVGInternalImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) +{ + bool tileHorizontal = (wrapMode == QSGTexture::Repeat); + if (tileHorizontal == m_tileHorizontal) + return; + + m_tileHorizontal = tileHorizontal; + markDirty(DirtyMaterial); +} + +void QSGOpenVGInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrapMode) +{ + bool tileVertical = (wrapMode == QSGTexture::Repeat); + if (tileVertical == m_tileVertical) + return; + + m_tileVertical = (wrapMode == QSGTexture::Repeat); + markDirty(DirtyMaterial); +} + +void QSGOpenVGInternalImageNode::update() +{ +} + +void QSGOpenVGInternalImageNode::preprocess() +{ + bool doDirty = false; + QSGLayer *t = qobject_cast<QSGLayer *>(m_texture); + if (t) { + doDirty = t->updateTexture(); + markDirty(DirtyGeometry); + } + if (doDirty) + markDirty(DirtyMaterial); +} + +QT_END_NAMESPACE + + + + diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.h b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.h new file mode 100644 index 0000000000..2361aa4892 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvginternalimagenode.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGINTERNALIMAGENODE_H +#define QSGOPENVGINTERNALIMAGENODE_H + +#include <private/qsgadaptationlayer_p.h> +#include "qsgopenvgrenderable.h" + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGInternalImageNode : public QSGInternalImageNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGInternalImageNode(); + ~QSGOpenVGInternalImageNode(); + + void render() override; + + void setTargetRect(const QRectF &rect) override; + void setInnerTargetRect(const QRectF &rect) override; + void setInnerSourceRect(const QRectF &rect) override; + void setSubSourceRect(const QRectF &rect) override; + void setTexture(QSGTexture *texture) override; + void setMirror(bool mirror) override; + void setMipmapFiltering(QSGTexture::Filtering filtering) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) override; + void setVerticalWrapMode(QSGTexture::WrapMode wrapMode) override; + void update() override; + + void preprocess() override; + +private: + + QRectF m_targetRect; + QRectF m_innerTargetRect; + QRectF m_innerSourceRect = QRectF(0, 0, 1, 1); + QRectF m_subSourceRect = QRectF(0, 0, 1, 1); + + bool m_mirror = false; + bool m_smooth = true; + bool m_tileHorizontal = false; + bool m_tileVertical = false; + + QSGTexture *m_texture = nullptr; + + VGImage m_subSourceRectImage = 0; + bool m_subSourceRectImageDirty = true; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGINTERNALIMAGENODE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp new file mode 100644 index 0000000000..372dffbbc2 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.cpp @@ -0,0 +1,613 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvginternalrectanglenode.h" +#include "qsgopenvghelpers.h" + +#include <VG/vgu.h> + +QSGOpenVGInternalRectangleNode::QSGOpenVGInternalRectangleNode() +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); + createVGResources(); +} + +QSGOpenVGInternalRectangleNode::~QSGOpenVGInternalRectangleNode() +{ + destroyVGResources(); +} + + +void QSGOpenVGInternalRectangleNode::setRect(const QRectF &rect) +{ + m_rect = rect; + m_pathDirty = true; +} + +void QSGOpenVGInternalRectangleNode::setColor(const QColor &color) +{ + m_fillColor = color; + m_fillDirty = true; +} + +void QSGOpenVGInternalRectangleNode::setPenColor(const QColor &color) +{ + m_strokeColor = color; + m_strokeDirty = true; +} + +void QSGOpenVGInternalRectangleNode::setPenWidth(qreal width) +{ + m_penWidth = width; + m_strokeDirty = true; + m_pathDirty = true; +} + +//Move first stop by pos relative to seconds +static QGradientStop interpolateStop(const QGradientStop &firstStop, const QGradientStop &secondStop, double newPos) +{ + double distance = secondStop.first - firstStop.first; + double distanceDelta = newPos - firstStop.first; + double modifierValue = distanceDelta / distance; + int redDelta = (secondStop.second.red() - firstStop.second.red()) * modifierValue; + int greenDelta = (secondStop.second.green() - firstStop.second.green()) * modifierValue; + int blueDelta = (secondStop.second.blue() - firstStop.second.blue()) * modifierValue; + int alphaDelta = (secondStop.second.alpha() - firstStop.second.alpha()) * modifierValue; + + QGradientStop newStop; + newStop.first = newPos; + newStop.second = QColor(firstStop.second.red() + redDelta, + firstStop.second.green() + greenDelta, + firstStop.second.blue() + blueDelta, + firstStop.second.alpha() + alphaDelta); + + return newStop; +} + +void QSGOpenVGInternalRectangleNode::setGradientStops(const QGradientStops &stops) +{ + + //normalize stops + bool needsNormalization = false; + for (const QGradientStop &stop : qAsConst(stops)) { + if (stop.first < 0.0 || stop.first > 1.0) { + needsNormalization = true; + continue; + } + } + + if (needsNormalization) { + QGradientStops normalizedStops; + if (stops.count() == 1) { + //If there is only one stop, then the position does not matter + //It is just treated as a color + QGradientStop stop = stops.at(0); + stop.first = 0.0; + normalizedStops.append(stop); + } else { + //Clip stops to only the first below 0.0 and above 1.0 + int below = -1; + int above = -1; + QVector<int> between; + for (int i = 0; i < stops.count(); ++i) { + if (stops.at(i).first < 0.0) { + below = i; + } else if (stops.at(i).first > 1.0) { + above = i; + break; + } else { + between.append(i); + } + } + + //Interpoloate new color values for above and below + if (below != -1 ) { + //If there are more than one stops left, interpolate + if (below + 1 < stops.count()) { + normalizedStops.append(interpolateStop(stops.at(below), stops.at(below + 1), 0.0)); + } else { + QGradientStop singleStop; + singleStop.first = 0.0; + singleStop.second = stops.at(below).second; + normalizedStops.append(singleStop); + } + } + + for (int i = 0; i < between.count(); ++i) + normalizedStops.append(stops.at(between.at(i))); + + if (above != -1) { + //If there stops before above, interpolate + if (above >= 1) { + normalizedStops.append(interpolateStop(stops.at(above), stops.at(above - 1), 1.0)); + } else { + QGradientStop singleStop; + singleStop.first = 1.0; + singleStop.second = stops.at(above).second; + normalizedStops.append(singleStop); + } + } + } + + m_gradientStops = normalizedStops; + + } else { + m_gradientStops = stops; + } + + m_fillDirty = true; +} + +void QSGOpenVGInternalRectangleNode::setRadius(qreal radius) +{ + m_radius = radius; + m_pathDirty = true; +} + +void QSGOpenVGInternalRectangleNode::setAligned(bool aligned) +{ + m_aligned = aligned; +} + +void QSGOpenVGInternalRectangleNode::update() +{ +} + +void QSGOpenVGInternalRectangleNode::render() +{ + // If path is dirty + if (m_pathDirty) { + vgClearPath(m_rectanglePath, VG_PATH_CAPABILITY_APPEND_TO); + vgClearPath(m_borderPath, VG_PATH_CAPABILITY_APPEND_TO); + + if (m_penWidth == 0) { + generateRectanglePath(m_rect, m_radius, m_rectanglePath); + } else { + generateRectangleAndBorderPaths(m_rect, m_penWidth, m_radius, m_rectanglePath, m_borderPath); + } + + m_pathDirty = false; + } + + //If fill is drity + if (m_fillDirty) { + if (m_gradientStops.isEmpty()) { + vgSetParameteri(m_rectanglePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(m_rectanglePaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_fillColor, opacity()).constData()); + } else { + // Linear Gradient + vgSetParameteri(m_rectanglePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_LINEAR_GRADIENT); + const VGfloat verticalLinearGradient[] = { + 0.0f, + 0.0f, + 0.0f, + static_cast<VGfloat>(m_rect.height()) + }; + vgSetParameterfv(m_rectanglePaint, VG_PAINT_LINEAR_GRADIENT, 4, verticalLinearGradient); + vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_PAD); + vgSetParameteri(m_rectanglePaint, VG_PAINT_COLOR_RAMP_PREMULTIPLIED, false); + + QVector<VGfloat> stops; + for (const QGradientStop &stop : qAsConst(m_gradientStops)) { + // offset + stops.append(stop.first); + // color + stops.append(QSGOpenVGHelpers::qColorToVGColor(stop.second, opacity())); + } + + vgSetParameterfv(m_rectanglePaint, VG_PAINT_COLOR_RAMP_STOPS, stops.length(), stops.constData()); + } + + m_fillDirty = false; + } + + //If stroke is dirty + if (m_strokeDirty) { + vgSetParameteri(m_borderPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(m_borderPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_strokeColor, opacity()).constData()); + + m_strokeDirty = false; + } + + //Draw + if (m_penWidth > 0) { + vgSetPaint(m_borderPaint, VG_FILL_PATH); + vgDrawPath(m_borderPath, VG_FILL_PATH); + vgSetPaint(m_rectanglePaint, VG_FILL_PATH); + vgDrawPath(m_rectanglePath, VG_FILL_PATH); + } else { + vgSetPaint(m_rectanglePaint, VG_FILL_PATH); + vgDrawPath(m_rectanglePath, VG_FILL_PATH); + } +} + +void QSGOpenVGInternalRectangleNode::setOpacity(float opacity) +{ + if (opacity != QSGOpenVGRenderable::opacity()) { + QSGOpenVGRenderable::setOpacity(opacity); + m_strokeDirty = true; + m_fillDirty = true; + } +} + +void QSGOpenVGInternalRectangleNode::createVGResources() +{ + m_rectanglePaint = vgCreatePaint(); + m_borderPaint = vgCreatePaint(); + m_rectanglePath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, + VG_PATH_CAPABILITY_APPEND_TO); + m_borderPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, + VG_PATH_CAPABILITY_APPEND_TO); +} + +void QSGOpenVGInternalRectangleNode::destroyVGResources() +{ + vgDestroyPaint(m_rectanglePaint); + vgDestroyPaint(m_borderPaint); + vgDestroyPath(m_rectanglePath); + vgDestroyPath(m_borderPath); +} + +void QSGOpenVGInternalRectangleNode::generateRectanglePath(const QRectF &rect, float radius, VGPath path) const +{ + if (radius == 0) { + // Generate a rectangle + + // Create command list + static const VGubyte rectCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Create command data + QVector<VGfloat> coordinates(5); + coordinates[0] = rect.x(); + coordinates[1] = rect.y(); + coordinates[2] = rect.width(); + coordinates[3] = rect.height(); + coordinates[4] = -rect.width(); + + vgAppendPathData(path, 5, rectCommands, coordinates.constData()); + } else { + // Generate a rounded rectangle + //Radius should never exceeds half of the width or half of the height + float adjustedRadius = qMin((float)qMin(rect.width(), rect.height()) * 0.5f, radius); + + // OpenVG expectes radius to be 2x what we expect + adjustedRadius *= 2; + + // Create command list + static const VGubyte roundedRectCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_CLOSE_PATH + }; + + // Create command data + QVector<VGfloat> coordinates(26); + + coordinates[0] = rect.x() + adjustedRadius / 2; + coordinates[1] = rect.y(); + + coordinates[2] = rect.width() - adjustedRadius; + + coordinates[3] = adjustedRadius / 2; + coordinates[4] = adjustedRadius / 2; + coordinates[5] = 0; + coordinates[6] = adjustedRadius / 2; + coordinates[7] = adjustedRadius / 2; + + coordinates[8] = rect.height() - adjustedRadius; + + coordinates[9] = adjustedRadius / 2; + coordinates[10] = adjustedRadius / 2; + coordinates[11] = 0; + coordinates[12] = -adjustedRadius / 2; + coordinates[13] = adjustedRadius / 2; + + coordinates[14] = -(rect.width() - adjustedRadius); + + coordinates[15] = adjustedRadius / 2; + coordinates[16] = adjustedRadius / 2; + coordinates[17] = 0; + coordinates[18] = -adjustedRadius / 2; + coordinates[19] = -adjustedRadius / 2; + + coordinates[20] = -(rect.height() - adjustedRadius); + + coordinates[21] = adjustedRadius / 2; + coordinates[22] = adjustedRadius / 2; + coordinates[23] = 0; + coordinates[24] = adjustedRadius / 2; + coordinates[25] = -adjustedRadius / 2; + + vgAppendPathData(path, 10, roundedRectCommands, coordinates.constData()); + } +} + +void QSGOpenVGInternalRectangleNode::generateBorderPath(const QRectF &rect, float borderWidth, float borderHeight, float radius, VGPath path) const +{ + if (radius == 0) { + // squared frame + // Create command list + static const VGubyte squaredBorderCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_MOVE_TO_ABS, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Create command data + QVector<VGfloat> coordinates(10); + // Outside Square + coordinates[0] = rect.x(); + coordinates[1] = rect.y(); + coordinates[2] = rect.width(); + coordinates[3] = rect.height(); + coordinates[4] = -rect.width(); + // Inside Square (opposite direction) + coordinates[5] = rect.x() + borderWidth; + coordinates[6] = rect.y() + borderHeight; + coordinates[7] = rect.height() - (borderHeight * 2); + coordinates[8] = rect.width() - (borderWidth * 2); + coordinates[9] = -(rect.height() - (borderHeight * 2)); + + vgAppendPathData(path, 9, squaredBorderCommands, coordinates.constData()); + } else if (radius < qMax(borderWidth, borderHeight)){ + // rounded outside, squared inside + // Create command list + static const VGubyte roundedRectCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_MOVE_TO_ABS, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Ajust for OpenVG's usage or radius + float adjustedRadius = radius * 2; + + // Create command data + QVector<VGfloat> coordinates(31); + // Outside Rounded Rect + coordinates[0] = rect.x() + adjustedRadius / 2; + coordinates[1] = rect.y(); + + coordinates[2] = rect.width() - adjustedRadius; + + coordinates[3] = adjustedRadius / 2; + coordinates[4] = adjustedRadius / 2; + coordinates[5] = 0; + coordinates[6] = adjustedRadius / 2; + coordinates[7] = adjustedRadius / 2; + + coordinates[8] = rect.height() - adjustedRadius; + + coordinates[9] = adjustedRadius / 2; + coordinates[10] = adjustedRadius / 2; + coordinates[11] = 0; + coordinates[12] = -adjustedRadius / 2; + coordinates[13] = adjustedRadius / 2; + + coordinates[14] = -(rect.width() - adjustedRadius); + + coordinates[15] = adjustedRadius / 2; + coordinates[16] = adjustedRadius / 2; + coordinates[17] = 0; + coordinates[18] = -adjustedRadius / 2; + coordinates[19] = -adjustedRadius / 2; + + coordinates[20] = -(rect.height() - adjustedRadius); + + coordinates[21] = adjustedRadius / 2; + coordinates[22] = adjustedRadius / 2; + coordinates[23] = 0; + coordinates[24] = adjustedRadius / 2; + coordinates[25] = -adjustedRadius / 2; + + // Inside Square (opposite direction) + coordinates[26] = rect.x() + borderWidth; + coordinates[27] = rect.y() + borderHeight; + coordinates[28] = rect.height() - (borderHeight * 2); + coordinates[29] = rect.width() - (borderWidth * 2); + coordinates[30] = -(rect.height() - (borderHeight * 2)); + + vgAppendPathData(path, 14, roundedRectCommands, coordinates.constData()); + } else { + // rounded outside, rounded inside + + static const VGubyte roundedBorderCommands[] = { + // Outer + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCCWARC_TO_REL, + // Inner + VG_MOVE_TO_ABS, + VG_SCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_SCWARC_TO_REL, + VG_VLINE_TO_REL, + VG_SCWARC_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Adjust for OpenVG's usage or radius + float adjustedRadius = radius * 2; + float adjustedInnerRadius = (radius - qMax(borderWidth, borderHeight)) * 2; + + // Create command data + QVector<VGfloat> coordinates(52); + + // Outer + coordinates[0] = rect.x() + adjustedRadius / 2; + coordinates[1] = rect.y(); + + coordinates[2] = rect.width() - adjustedRadius; + + coordinates[3] = adjustedRadius / 2; + coordinates[4] = adjustedRadius / 2; + coordinates[5] = 0; + coordinates[6] = adjustedRadius / 2; + coordinates[7] = adjustedRadius / 2; + + coordinates[8] = rect.height() - adjustedRadius; + + coordinates[9] = adjustedRadius / 2; + coordinates[10] = adjustedRadius / 2; + coordinates[11] = 0; + coordinates[12] = -adjustedRadius / 2; + coordinates[13] = adjustedRadius / 2; + + coordinates[14] = -(rect.width() - adjustedRadius); + + coordinates[15] = adjustedRadius / 2; + coordinates[16] = adjustedRadius / 2; + coordinates[17] = 0; + coordinates[18] = -adjustedRadius / 2; + coordinates[19] = -adjustedRadius / 2; + + coordinates[20] = -(rect.height() - adjustedRadius); + + coordinates[21] = adjustedRadius / 2; + coordinates[22] = adjustedRadius / 2; + coordinates[23] = 0; + coordinates[24] = adjustedRadius / 2; + coordinates[25] = -adjustedRadius / 2; + + // Inner + coordinates[26] = rect.width() - (adjustedInnerRadius / 2 + borderWidth); + coordinates[27] = rect.height() - borderHeight; + + coordinates[28] = adjustedInnerRadius / 2; + coordinates[29] = adjustedInnerRadius / 2; + coordinates[30] = 0; + coordinates[31] = adjustedInnerRadius / 2; + coordinates[32] = -adjustedInnerRadius / 2; + + coordinates[33] = -((rect.height() - borderHeight * 2) - adjustedInnerRadius); + + coordinates[34] = adjustedInnerRadius / 2; + coordinates[35] = adjustedInnerRadius / 2; + coordinates[36] = 0; + coordinates[37] = -adjustedInnerRadius / 2; + coordinates[38] = -adjustedInnerRadius / 2; + + coordinates[39] = -((rect.width() - borderWidth * 2) - adjustedInnerRadius); + + coordinates[40] = adjustedInnerRadius / 2; + coordinates[41] = adjustedInnerRadius / 2; + coordinates[42] = 0; + coordinates[43] = -adjustedInnerRadius / 2; + coordinates[44] = adjustedInnerRadius / 2; + + coordinates[45] = (rect.height() - borderHeight * 2) - adjustedInnerRadius; + + coordinates[46] = adjustedInnerRadius / 2; + coordinates[47] = adjustedInnerRadius / 2; + coordinates[48] = 0; + coordinates[49] = adjustedInnerRadius / 2; + coordinates[50] = adjustedInnerRadius / 2; + + coordinates[51] = (rect.width() - borderWidth * 2) - adjustedInnerRadius; + + vgAppendPathData(path, 19, roundedBorderCommands, coordinates.constData()); + } +} + +void QSGOpenVGInternalRectangleNode::generateRectangleAndBorderPaths(const QRectF &rect, float penWidth, float radius, VGPath inside, VGPath outside) const +{ + //Borders can not be more than half the height/width of a rect + float borderWidth = qMin(penWidth, (float)rect.width() * 0.5f); + float borderHeight = qMin(penWidth, (float)rect.height() * 0.5f); + + //Radius should never exceeds half of the width or half of the height + float adjustedRadius = qMin((float)qMin(rect.width(), rect.height()) * 0.5f, radius); + + QRectF innerRect = rect; + innerRect.adjust(borderWidth, borderHeight, -borderWidth, -borderHeight); + + if (radius == 0) { + // Regular rect with border + generateRectanglePath(innerRect, 0, inside); + generateBorderPath(rect, borderWidth, borderHeight, 0, outside); + } else { + // Rounded Rect with border + float innerRadius = radius - qMax(borderWidth, borderHeight); + if (innerRadius < 0) + innerRadius = 0.0f; + + generateRectanglePath(innerRect, innerRadius, inside); + generateBorderPath(rect, borderWidth, borderHeight, adjustedRadius, outside); + } +} diff --git a/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h new file mode 100644 index 0000000000..0d5283773f --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvginternalrectanglenode.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGINTERNALRECTANGLENODE_H +#define QSGOPENVGINTERNALRECTANGLENODE_H + +#include <private/qsgadaptationlayer_p.h> +#include "qsgopenvgrenderable.h" + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGInternalRectangleNode : public QSGInternalRectangleNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGInternalRectangleNode(); + ~QSGOpenVGInternalRectangleNode(); + + void setRect(const QRectF &rect) override; + void setColor(const QColor &color) override; + void setPenColor(const QColor &color) override; + void setPenWidth(qreal width) override; + void setGradientStops(const QGradientStops &stops) override; + void setRadius(qreal radius) override; + void setAligned(bool aligned) override; + void update() override; + + void render() override; + void setOpacity(float opacity) override; + +private: + void createVGResources(); + void destroyVGResources(); + + void generateRectanglePath(const QRectF &rect, float radius, VGPath path) const; + void generateRectangleAndBorderPaths(const QRectF &rect, float penWidth, float radius, VGPath inside, VGPath outside) const; + void generateBorderPath(const QRectF &rect, float borderWidth, float borderHeight, float radius, VGPath path) const; + + bool m_pathDirty = true; + bool m_fillDirty = true; + bool m_strokeDirty = true; + + QRectF m_rect; + QColor m_fillColor; + QColor m_strokeColor; + qreal m_penWidth = 0.0; + qreal m_radius = 0.0; + bool m_aligned = false; + QGradientStops m_gradientStops; + + VGPath m_rectanglePath; + VGPath m_borderPath; + VGPaint m_rectanglePaint; + VGPaint m_borderPaint; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGINTERNALRECTANGLENODE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp b/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp new file mode 100644 index 0000000000..03a82ca4ee --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvglayer.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvglayer.h" +#include "qsgopenvgrenderer_p.h" +#include "qsgopenvgcontext_p.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGLayer::QSGOpenVGLayer(QSGRenderContext *renderContext) + : m_item(nullptr) + , m_renderer(nullptr) + , m_device_pixel_ratio(1) + , m_mirrorHorizontal(false) + , m_mirrorVertical(false) + , m_live(true) + , m_grab(true) + , m_recursive(false) + , m_dirtyTexture(true) + , m_image(0) + , m_renderTarget(0) + , m_layerContext(0) +{ + m_context = static_cast<QSGOpenVGRenderContext*>(renderContext); + m_vgContext = m_context->vgContext(); +} + +QSGOpenVGLayer::~QSGOpenVGLayer() +{ + invalidated(); +} + +int QSGOpenVGLayer::textureId() const +{ + return static_cast<int>(m_image); +} + +QSize QSGOpenVGLayer::textureSize() const +{ + if (m_image != 0) { + VGint imageWidth = vgGetParameteri(m_image, VG_IMAGE_WIDTH); + VGint imageHeight = vgGetParameteri(m_image, VG_IMAGE_HEIGHT); + return QSize(imageWidth, imageHeight); + } + + return QSize(); +} + +bool QSGOpenVGLayer::hasAlphaChannel() const +{ + VGImageFormat format = static_cast<VGImageFormat>(vgGetParameteri(m_image, VG_IMAGE_FORMAT)); + + switch (format) { + case VG_sRGBA_8888: + case VG_sRGBA_8888_PRE: + case VG_sRGBA_5551: + case VG_sRGBA_4444: + case VG_lRGBA_8888: + case VG_lRGBA_8888_PRE: + case VG_A_8: + case VG_A_1: + case VG_A_4: + case VG_sARGB_8888: + case VG_sARGB_8888_PRE: + case VG_sARGB_1555: + case VG_sARGB_4444: + case VG_lARGB_8888: + case VG_lARGB_8888_PRE: + case VG_sBGRA_8888: + case VG_sBGRA_8888_PRE: + case VG_sBGRA_5551: + case VG_sBGRA_4444: + case VG_lBGRA_8888: + case VG_lBGRA_8888_PRE: + case VG_sABGR_8888: + case VG_sABGR_8888_PRE: + case VG_sABGR_1555: + case VG_sABGR_4444: + case VG_lABGR_8888: + case VG_lABGR_8888_PRE: + return true; + break; + default: + break; + } + return false; +} + +bool QSGOpenVGLayer::hasMipmaps() const +{ + return false; +} + +void QSGOpenVGLayer::bind() +{ +} + +bool QSGOpenVGLayer::updateTexture() +{ + bool doGrab = (m_live || m_grab) && m_dirtyTexture; + if (doGrab) + grab(); + if (m_grab) + emit scheduledUpdateCompleted(); + m_grab = false; + return doGrab; +} + +void QSGOpenVGLayer::setItem(QSGNode *item) +{ + if (item == m_item) + return; + m_item = item; + + if (m_live && !m_item) { + vgDestroyImage(m_image); + m_image = 0; + } + + markDirtyTexture(); +} + +void QSGOpenVGLayer::setRect(const QRectF &rect) +{ + if (rect == m_rect) + return; + m_rect = rect; + markDirtyTexture(); +} + +void QSGOpenVGLayer::setSize(const QSize &size) +{ + if (size == m_size) + return; + m_size = size; + + if (m_live && m_size.isNull()) { + vgDestroyImage(m_image); + m_image = 0; + } + + markDirtyTexture(); +} + +void QSGOpenVGLayer::scheduleUpdate() +{ + if (m_grab) + return; + m_grab = true; + if (m_dirtyTexture) { + emit updateRequested(); + } +} + +QImage QSGOpenVGLayer::toImage() const +{ + // XXX + return QImage(); +} + +void QSGOpenVGLayer::setLive(bool live) +{ + if (live == m_live) + return; + m_live = live; + + if (m_live && (!m_item || m_size.isNull())) { + vgDestroyImage(m_image); + m_image = 0; + } + + markDirtyTexture(); +} + +void QSGOpenVGLayer::setRecursive(bool recursive) +{ + m_recursive = recursive; +} + +void QSGOpenVGLayer::setFormat(uint format) +{ + Q_UNUSED(format) +} + +void QSGOpenVGLayer::setHasMipmaps(bool mipmap) +{ + Q_UNUSED(mipmap) +} + +void QSGOpenVGLayer::setDevicePixelRatio(qreal ratio) +{ + m_device_pixel_ratio = ratio; +} + +void QSGOpenVGLayer::setMirrorHorizontal(bool mirror) +{ + if (m_mirrorHorizontal == mirror) + return; + m_mirrorHorizontal = mirror; + markDirtyTexture(); +} + +void QSGOpenVGLayer::setMirrorVertical(bool mirror) +{ + if (m_mirrorVertical == mirror) + return; + m_mirrorVertical = mirror; + markDirtyTexture(); +} + +void QSGOpenVGLayer::markDirtyTexture() +{ + m_dirtyTexture = true; + if (m_live || m_grab) { + emit updateRequested(); + } +} + +void QSGOpenVGLayer::invalidated() +{ + delete m_renderer; + m_renderer = 0; +} + +void QSGOpenVGLayer::grab() +{ + if (!m_item || m_size.isNull()) { + vgDestroyImage(m_image); + m_image = 0; + m_dirtyTexture = false; + return; + } + QSGNode *root = m_item; + while (root->firstChild() && root->type() != QSGNode::RootNodeType) + root = root->firstChild(); + if (root->type() != QSGNode::RootNodeType) + return; + + if (!m_renderer) { + m_renderer = new QSGOpenVGRenderer(m_context); + connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture())); + } + m_renderer->setDevicePixelRatio(m_device_pixel_ratio); + m_renderer->setRootNode(static_cast<QSGRootNode *>(root)); + + if (m_image == 0 || m_imageSize != m_size ) { + if (m_image != 0) + vgDestroyImage(m_image); + + m_image = vgCreateImage(VG_lARGB_8888_PRE, m_size.width(), m_size.height(), VG_IMAGE_QUALITY_BETTER); + m_imageSize = m_size; + + //Destroy old RenderTarget + if (m_renderTarget != 0) + eglDestroySurface(m_vgContext->eglDisplay(), m_renderTarget); + + const EGLint configAttribs[] = { + EGL_CONFORMANT, EGL_OPENVG_BIT, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_ALPHA_MASK_SIZE, 8, + EGL_NONE + }; + + EGLConfig pbufferConfig; + EGLint numConfig; + eglChooseConfig(m_vgContext->eglDisplay(), configAttribs, &pbufferConfig, 1, &numConfig); + + if (m_layerContext == 0) { + // Create new context + m_layerContext = eglCreateContext(m_vgContext->eglDisplay(), pbufferConfig, m_vgContext->eglContext(), 0); + } + + m_renderTarget = eglCreatePbufferFromClientBuffer(m_vgContext->eglDisplay(), + EGL_OPENVG_IMAGE, + (EGLClientBuffer)m_image, + pbufferConfig, + 0); + } + + if (m_renderTarget == EGL_NO_SURFACE) { + qDebug() << "invalid renderTarget!"; + return; + } + + // Render texture. + root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update. + m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update. + + m_dirtyTexture = false; + + m_renderer->setDeviceRect(m_size); + m_renderer->setViewportRect(m_size); + QRect mirrored(m_mirrorHorizontal ? m_rect.right() * m_device_pixel_ratio : m_rect.left() * m_device_pixel_ratio, + m_mirrorVertical ? m_rect.top() * m_device_pixel_ratio : m_rect.bottom() * m_device_pixel_ratio, + m_mirrorHorizontal ? -m_rect.width() * m_device_pixel_ratio : m_rect.width() * m_device_pixel_ratio, + m_mirrorVertical ? m_rect.height() * m_device_pixel_ratio : -m_rect.height() * m_device_pixel_ratio); + m_renderer->setProjectionMatrixToRect(mirrored); + m_renderer->setClearColor(Qt::transparent); + + eglMakeCurrent(m_vgContext->eglDisplay(), m_renderTarget, m_renderTarget, m_layerContext); + + // Before Rendering setup context for adjusting to Qt Coordinates to PixelBuffer + // Should already be inverted by default + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadIdentity(); + + m_renderer->renderScene(); + + eglSwapBuffers(m_vgContext->eglDisplay(), m_renderTarget); + + // make the default surface current again + m_vgContext->makeCurrent(); + + root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update. + + if (m_recursive) + markDirtyTexture(); // Continuously update if 'live' and 'recursive'. +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvglayer.h b/src/plugins/scenegraph/openvg/qsgopenvglayer.h new file mode 100644 index 0000000000..ee9984b9d9 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvglayer.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGLAYER_H +#define QSGOPENVGLAYER_H + +#include <private/qsgadaptationlayer_p.h> +#include <private/qsgcontext_p.h> + +#include "qopenvgcontext_p.h" + +QT_BEGIN_NAMESPACE + +class QSGOpenVGRenderer; +class QSGOpenVGRenderContext; + +class QSGOpenVGLayer : public QSGLayer +{ +public: + QSGOpenVGLayer(QSGRenderContext *renderContext); + ~QSGOpenVGLayer(); + + // QSGTexture interface +public: + int textureId() const override; + QSize textureSize() const override; + bool hasAlphaChannel() const override; + bool hasMipmaps() const override; + void bind() override; + + // QSGDynamicTexture interface +public: + bool updateTexture() override; + + // QSGLayer interface +public: + void setItem(QSGNode *item) override; + void setRect(const QRectF &rect) override; + void setSize(const QSize &size) override; + void scheduleUpdate() override; + QImage toImage() const override; + void setLive(bool live) override; + void setRecursive(bool recursive) override; + void setFormat(uint format) override; + void setHasMipmaps(bool mipmap) override; + void setDevicePixelRatio(qreal ratio) override; + void setMirrorHorizontal(bool mirror) override; + void setMirrorVertical(bool mirror) override; + +public slots: + void markDirtyTexture() override; + void invalidated() override; + +private: + void grab(); + + QSGNode *m_item; + QSGOpenVGRenderContext *m_context; + QSGOpenVGRenderer *m_renderer; + QRectF m_rect; + QSize m_size; + qreal m_device_pixel_ratio; + bool m_mirrorHorizontal; + bool m_mirrorVertical; + bool m_live; + bool m_grab; + bool m_recursive; + bool m_dirtyTexture; + + QOpenVGContext *m_vgContext; + VGImage m_image; + QSize m_imageSize; + EGLSurface m_renderTarget; + EGLContext m_layerContext; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGLAYER_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp new file mode 100644 index 0000000000..fc9f5eb57c --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgnodevisitor.h" +#include "qsgopenvginternalrectanglenode.h" +#include "qsgopenvginternalimagenode.h" +#include "qsgopenvgpublicnodes.h" +#include "qsgopenvgglyphnode_p.h" +#include "qsgopenvgpainternode.h" +#include "qsgopenvgspritenode.h" +#include "qsgopenvgrenderable.h" + +#include "qopenvgcontext_p.h" + +#include <QtQuick/qsgsimplerectnode.h> +#include <QtQuick/qsgsimpletexturenode.h> +#include <QtQuick/qsgrendernode.h> + +QT_BEGIN_NAMESPACE + +QSGOpenVGNodeVisitor::QSGOpenVGNodeVisitor() +{ + //Store the current matrix state + QVector<VGfloat> matrix(9); + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgGetMatrix(matrix.data()); + + m_transformStack.push(QOpenVGMatrix(matrix.constData())); + + // Opacity + m_opacityState.push(1.0f); +} + +bool QSGOpenVGNodeVisitor::visit(QSGTransformNode *node) +{ + const QVector<float> matrixData = { node->matrix().constData()[0], node->matrix().constData()[1], node->matrix().constData()[3], + node->matrix().constData()[4], node->matrix().constData()[5], node->matrix().constData()[7], + node->matrix().constData()[12], node->matrix().constData()[13], node->matrix().constData()[15] }; + const QOpenVGMatrix matrix2d(matrixData.constData()); + + m_transformStack.push(m_transformStack.top() * matrix2d); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGTransformNode *) +{ + m_transformStack.pop(); +} + +bool QSGOpenVGNodeVisitor::visit(QSGClipNode *node) +{ + VGMaskOperation maskOperation = VG_INTERSECT_MASK; + if (m_clipStack.count() == 0) { + vgSeti(VG_MASKING, VG_TRUE); + vgMask(0,VG_FILL_MASK, 0, 0, VG_MAXINT, VG_MAXINT); + } + + // Render clip node geometry to mask + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + VGPath clipPath = generateClipPath(node->clipRect()); + vgRenderToMask(clipPath, VG_FILL_PATH, maskOperation); + + auto clipState = new ClipState(clipPath, m_transformStack.top()); + m_clipStack.push(clipState); + + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGClipNode *) +{ + // Remove clip node geometry from mask + auto clipState = m_clipStack.pop(); + vgDestroyPath(clipState->path); + + if (m_clipStack.count() == 0) { + vgSeti(VG_MASKING, VG_FALSE); + } else { + // Recreate the mask + vgMask(0,VG_FILL_MASK, 0, 0, VG_MAXINT, VG_MAXINT); + for (auto state : m_clipStack) { + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(state->transform.constData()); + vgRenderToMask(state->path, VG_FILL_PATH, VG_INTERSECT_MASK); + } + } + + delete clipState; +} + +bool QSGOpenVGNodeVisitor::visit(QSGGeometryNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + if (QSGSimpleRectNode *rectNode = dynamic_cast<QSGSimpleRectNode *>(node)) { + // TODO: Try and render the QSGSimpleRectNode + Q_UNUSED(rectNode) + return false; + } else if (QSGSimpleTextureNode *tn = dynamic_cast<QSGSimpleTextureNode *>(node)) { + // TODO: Try and render the QSGSimpleTextureNode + Q_UNUSED(tn) + return false; + } else if (QSGOpenVGNinePatchNode *nn = dynamic_cast<QSGOpenVGNinePatchNode *>(node)) { + renderRenderableNode(nn); + } else if (QSGOpenVGRectangleNode *rn = dynamic_cast<QSGOpenVGRectangleNode *>(node)) { + renderRenderableNode(rn); + } else if (QSGOpenVGImageNode *n = dynamic_cast<QSGOpenVGImageNode *>(node)) { + renderRenderableNode(n); + } else { + // We dont know, so skip + return false; + } + + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGGeometryNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGOpacityNode *node) +{ + m_opacityState.push(m_opacityState.top() * node->opacity()); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGOpacityNode *) +{ + m_opacityState.pop(); +} + +bool QSGOpenVGNodeVisitor::visit(QSGInternalImageNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + renderRenderableNode(static_cast<QSGOpenVGInternalImageNode*>(node)); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGInternalImageNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGPainterNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + renderRenderableNode(static_cast<QSGOpenVGPainterNode*>(node)); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGPainterNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGInternalRectangleNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + renderRenderableNode(static_cast<QSGOpenVGInternalRectangleNode*>(node)); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGInternalRectangleNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGGlyphNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_GLYPH_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + renderRenderableNode(static_cast<QSGOpenVGGlyphNode*>(node)); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGGlyphNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGRootNode *) +{ + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGRootNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGSpriteNode *node) +{ + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadMatrix(m_transformStack.top().constData()); + renderRenderableNode(static_cast<QSGOpenVGSpriteNode*>(node)); + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGSpriteNode *) +{ +} + +bool QSGOpenVGNodeVisitor::visit(QSGRenderNode *) +{ + return true; +} + +void QSGOpenVGNodeVisitor::endVisit(QSGRenderNode *) +{ +} + +VGPath QSGOpenVGNodeVisitor::generateClipPath(const QRectF &rect) const +{ + VGPath clipPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, + VG_PATH_CAPABILITY_APPEND_TO); + + // Create command list + static const VGubyte rectCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Create command data + QVector<VGfloat> coordinates(5); + coordinates[0] = rect.x(); + coordinates[1] = rect.y(); + coordinates[2] = rect.width(); + coordinates[3] = rect.height(); + coordinates[4] = -rect.width(); + + vgAppendPathData(clipPath, 5, rectCommands, coordinates.constData()); + return clipPath; +} + +void QSGOpenVGNodeVisitor::renderRenderableNode(QSGOpenVGRenderable *node) +{ + if (!node) + return; + + node->setOpacity(m_opacityState.top()); + node->render(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.h b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.h new file mode 100644 index 0000000000..3105f2076d --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgnodevisitor.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGNODEVISITOR_H +#define QSGOPENVGNODEVISITOR_H + +#include <private/qsgadaptationlayer_p.h> +#include <QtCore/QStack> + +#include "qopenvgmatrix.h" + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGRenderable; +class QSGOpenVGNodeVisitor : public QSGNodeVisitorEx +{ +public: + QSGOpenVGNodeVisitor(); + + bool visit(QSGTransformNode *) override; + void endVisit(QSGTransformNode *) override; + bool visit(QSGClipNode *) override; + void endVisit(QSGClipNode *) override; + bool visit(QSGGeometryNode *) override; + void endVisit(QSGGeometryNode *) override; + bool visit(QSGOpacityNode *) override; + void endVisit(QSGOpacityNode *) override; + bool visit(QSGInternalImageNode *) override; + void endVisit(QSGInternalImageNode *) override; + bool visit(QSGPainterNode *) override; + void endVisit(QSGPainterNode *) override; + bool visit(QSGInternalRectangleNode *) override; + void endVisit(QSGInternalRectangleNode *) override; + bool visit(QSGGlyphNode *) override; + void endVisit(QSGGlyphNode *) override; + bool visit(QSGRootNode *) override; + void endVisit(QSGRootNode *) override; + bool visit(QSGSpriteNode *) override; + void endVisit(QSGSpriteNode *) override; + bool visit(QSGRenderNode *) override; + void endVisit(QSGRenderNode *) override; + +private: + struct ClipState { + ClipState(VGPath p, QOpenVGMatrix t) + { + path = p; + transform = t; + } + + VGPath path; + QOpenVGMatrix transform; + }; + + VGPath generateClipPath(const QRectF &rect) const; + void renderRenderableNode(QSGOpenVGRenderable *node); + + + QStack<QOpenVGMatrix> m_transformStack; + QStack<float> m_opacityState; + QStack<ClipState*> m_clipStack; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGNODEVISITOR_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpainternode.cpp b/src/plugins/scenegraph/openvg/qsgopenvgpainternode.cpp new file mode 100644 index 0000000000..c09ca6a47e --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgpainternode.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgpainternode.h" +#include "qsgopenvgtexture.h" +#include <qmath.h> + +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +QSGOpenVGPainterNode::QSGOpenVGPainterNode(QQuickPaintedItem *item) + : m_preferredRenderTarget(QQuickPaintedItem::Image) + , m_item(item) + , m_texture(nullptr) + , m_dirtyContents(false) + , m_opaquePainting(false) + , m_linear_filtering(false) + , m_smoothPainting(false) + , m_fillColor(Qt::transparent) + , m_contentsScale(1.0) + , m_dirtyGeometry(false) +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +QSGOpenVGPainterNode::~QSGOpenVGPainterNode() +{ + delete m_texture; +} + +void QSGOpenVGPainterNode::setPreferredRenderTarget(QQuickPaintedItem::RenderTarget) +{ +} + +void QSGOpenVGPainterNode::setSize(const QSize &size) +{ + if (size == m_size) + return; + + m_size = size; + + m_dirtyGeometry = true; +} + +void QSGOpenVGPainterNode::setDirty(const QRect &dirtyRect) +{ + m_dirtyContents = true; + m_dirtyRect = dirtyRect; + markDirty(DirtyMaterial); +} + +void QSGOpenVGPainterNode::setOpaquePainting(bool opaque) +{ + if (opaque == m_opaquePainting) + return; + + m_opaquePainting = opaque; +} + +void QSGOpenVGPainterNode::setLinearFiltering(bool linearFiltering) +{ + if (linearFiltering == m_linear_filtering) + return; + + m_linear_filtering = linearFiltering; +} + +void QSGOpenVGPainterNode::setMipmapping(bool) +{ + +} + +void QSGOpenVGPainterNode::setSmoothPainting(bool s) +{ + if (s == m_smoothPainting) + return; + + m_smoothPainting = s; +} + +void QSGOpenVGPainterNode::setFillColor(const QColor &c) +{ + if (c == m_fillColor) + return; + + m_fillColor = c; + markDirty(DirtyMaterial); +} + +void QSGOpenVGPainterNode::setContentsScale(qreal s) +{ + if (s == m_contentsScale) + return; + + m_contentsScale = s; + markDirty(DirtyMaterial); +} + +void QSGOpenVGPainterNode::setFastFBOResizing(bool) +{ +} + +void QSGOpenVGPainterNode::setTextureSize(const QSize &size) +{ + if (size == m_textureSize) + return; + + m_textureSize = size; + m_dirtyGeometry = true; +} + +QImage QSGOpenVGPainterNode::toImage() const +{ + return m_image; +} + +void QSGOpenVGPainterNode::update() +{ + if (m_dirtyGeometry) { + if (!m_opaquePainting) + m_image = QImage(m_size, QImage::Format_ARGB32_Premultiplied); + else + m_image = QImage(m_size, QImage::Format_RGB32); + } + + if (m_dirtyContents) + paint(); + + m_dirtyGeometry = false; + m_dirtyContents = false; +} + +QSGTexture *QSGOpenVGPainterNode::texture() const +{ + return m_texture; +} + +void QSGOpenVGPainterNode::render() +{ + if (!m_texture) + return; + + // Set Draw Mode + if (opacity() < 1.0) { + //Transparent + vgSetPaint(opacityPaint(), VG_FILL_PATH); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); + } else { + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + } + + if (m_linear_filtering) + vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_BETTER); + else + vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED); + + vgDrawImage(static_cast<VGImage>(m_texture->textureId())); +} + +void QSGOpenVGPainterNode::paint() +{ + QRect dirtyRect = m_dirtyRect.isNull() ? QRect(0, 0, m_size.width(), m_size.height()) : m_dirtyRect; + + QPainter painter; + + painter.begin(&m_image); + if (m_smoothPainting) { + painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); + } + + QRect clipRect; + + if (m_contentsScale == 1) { + qreal scaleX = m_textureSize.width() / (qreal) m_size.width(); + qreal scaleY = m_textureSize.height() / (qreal) m_size.height(); + painter.scale(scaleX, scaleY); + clipRect = dirtyRect; + } else { + painter.scale(m_contentsScale, m_contentsScale); + + QRect sclip(qFloor(dirtyRect.x()/m_contentsScale), + qFloor(dirtyRect.y()/m_contentsScale), + qCeil(dirtyRect.width()/m_contentsScale+dirtyRect.x()/m_contentsScale-qFloor(dirtyRect.x()/m_contentsScale)), + qCeil(dirtyRect.height()/m_contentsScale+dirtyRect.y()/m_contentsScale-qFloor(dirtyRect.y()/m_contentsScale))); + + clipRect = sclip; + } + + if (!m_dirtyRect.isNull()) + painter.setClipRect(clipRect); + + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(clipRect, m_fillColor); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + + m_item->paint(&painter); + painter.end(); + + m_dirtyRect = QRect(); + + if (m_texture) + delete m_texture; + + uint textureFlags = m_opaquePainting ? 0 : QSGRenderContext::CreateTexture_Alpha; + m_texture = new QSGOpenVGTexture(m_image, textureFlags); +} + +QT_END_NAMESPACE + + diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpainternode.h b/src/plugins/scenegraph/openvg/qsgopenvgpainternode.h new file mode 100644 index 0000000000..1fe992115f --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgpainternode.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGPAINTERNODE_H +#define QSGOPENVGPAINTERNODE_H + +#include <private/qsgadaptationlayer_p.h> +#include <QtQuick/QQuickPaintedItem> +#include "qsgopenvgrenderable.h" + +QT_BEGIN_NAMESPACE + +class QSGOpenVGTexture; + +class QSGOpenVGPainterNode : public QSGPainterNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGPainterNode(QQuickPaintedItem *item); + ~QSGOpenVGPainterNode(); + + void setPreferredRenderTarget(QQuickPaintedItem::RenderTarget target) override; + void setSize(const QSize &size) override; + void setDirty(const QRect &dirtyRect) override; + void setOpaquePainting(bool opaque) override; + void setLinearFiltering(bool linearFiltering) override; + void setMipmapping(bool mipmapping) override; + void setSmoothPainting(bool s) override; + void setFillColor(const QColor &c) override; + void setContentsScale(qreal s) override; + void setFastFBOResizing(bool dynamic) override; + void setTextureSize(const QSize &size) override; + QImage toImage() const override; + void update() override; + QSGTexture *texture() const override; + + void render() override; + void paint(); + +private: + QQuickPaintedItem::RenderTarget m_preferredRenderTarget; + + QQuickPaintedItem *m_item; + QSGOpenVGTexture *m_texture; + QImage m_image; + + QSize m_size; + bool m_dirtyContents; + QRect m_dirtyRect; + bool m_opaquePainting; + bool m_linear_filtering; + bool m_smoothPainting; + QColor m_fillColor; + qreal m_contentsScale; + QSize m_textureSize; + + bool m_dirtyGeometry; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGPAINTERNODE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp new file mode 100644 index 0000000000..f5890210a9 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.cpp @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgpublicnodes.h" +#include "qsgopenvghelpers.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGRectangleNode::QSGOpenVGRectangleNode() +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); + + m_rectPath = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0, 0, 0, + VG_PATH_CAPABILITY_APPEND_TO); + m_rectPaint = vgCreatePaint(); +} + +QSGOpenVGRectangleNode::~QSGOpenVGRectangleNode() +{ + vgDestroyPaint(m_rectPaint); + vgDestroyPath(m_rectPath); +} + +void QSGOpenVGRectangleNode::setRect(const QRectF &rect) +{ + m_rect = rect; + m_pathDirty = true; + markDirty(DirtyMaterial); +} + +void QSGOpenVGRectangleNode::setColor(const QColor &color) +{ + m_color = color; + m_paintDirty = true; + markDirty(DirtyMaterial); +} + +void QSGOpenVGRectangleNode::render() +{ + if (m_pathDirty) { + vgClearPath(m_rectPath, VG_PATH_CAPABILITY_APPEND_TO); + // Create command list + static const VGubyte rectCommands[] = { + VG_MOVE_TO_ABS, + VG_HLINE_TO_REL, + VG_VLINE_TO_REL, + VG_HLINE_TO_REL, + VG_CLOSE_PATH + }; + + // Create command data + QVector<VGfloat> coordinates(5); + coordinates[0] = m_rect.x(); + coordinates[1] = m_rect.y(); + coordinates[2] = m_rect.width(); + coordinates[3] = m_rect.height(); + coordinates[4] = -m_rect.width(); + + vgAppendPathData(m_rectPath, 5, rectCommands, coordinates.constData()); + m_pathDirty = false; + } + + if (m_paintDirty) { + vgSetPaint(m_rectPaint, VG_FILL_PATH); + vgSetParameteri(m_rectPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(m_rectPaint, VG_PAINT_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(m_color).constData()); + + m_paintDirty = false; + } + + vgSetPaint(m_rectPaint, VG_FILL_PATH); + vgDrawPath(m_rectPath, VG_FILL_PATH); + +} + +QSGOpenVGImageNode::QSGOpenVGImageNode() +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); + +} + +QSGOpenVGImageNode::~QSGOpenVGImageNode() +{ + if (m_owns) { + m_texture->deleteLater(); + } +} + +void QSGOpenVGImageNode::setTexture(QSGTexture *texture) +{ + m_texture = texture; + markDirty(DirtyMaterial); +} + +void QSGOpenVGImageNode::setTextureCoordinatesTransform(QSGImageNode::TextureCoordinatesTransformMode transformNode) +{ + if (m_transformMode == transformNode) + return; + m_transformMode = transformNode; + markDirty(DirtyGeometry); +} + +void QSGOpenVGImageNode::render() +{ + if (!m_texture) { + return; + } + + // Set Draw Mode + if (opacity() < 1.0) { + //Transparent + vgSetPaint(opacityPaint(), VG_FILL_PATH); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); + } else { + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + } + + VGImage image = static_cast<VGImage>(m_texture->textureId()); + + //Apply the TextureCoordinateTransform Flag + if (m_transformMode != QSGImageNode::NoTransform) { + float translateX = 0.0f; + float translateY = 0.0f; + float scaleX = 1.0f; + float scaleY = 1.0f; + + if (m_transformMode & QSGImageNode::MirrorHorizontally) { + translateX = m_rect.width(); + scaleX = -1.0; + } + + if (m_transformMode & QSGImageNode::MirrorVertically) { + translateY = m_rect.height(); + scaleY = -1.0; + } + + vgTranslate(translateX, translateY); + vgScale(scaleX, scaleY); + } + + // If the the source rect is the same as the target rect + if (m_sourceRect == m_rect) { + vgDrawImage(image); + } else { + // Scale + float scaleX = m_rect.width() / m_sourceRect.width(); + float scaleY = m_rect.height() / m_sourceRect.height(); + vgScale(scaleX, scaleY); + VGImage subImage = vgChildImage(image, m_sourceRect.x(), m_sourceRect.y(), m_sourceRect.width(), m_sourceRect.height()); + vgDrawImage(subImage); + vgDestroyImage(subImage); + } + +} + +QSGOpenVGNinePatchNode::QSGOpenVGNinePatchNode() +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); + +} + +void QSGOpenVGNinePatchNode::setTexture(QSGTexture *texture) +{ + m_texture = texture; + markDirty(DirtyMaterial); +} + +void QSGOpenVGNinePatchNode::setBounds(const QRectF &bounds) +{ + if (m_bounds == bounds) + return; + m_bounds = bounds; + markDirty(DirtyGeometry); +} + +void QSGOpenVGNinePatchNode::setDevicePixelRatio(qreal ratio) +{ + if (m_pixelRatio == ratio) + return; + m_pixelRatio = ratio; + markDirty(DirtyGeometry); +} + +void QSGOpenVGNinePatchNode::setPadding(qreal left, qreal top, qreal right, qreal bottom) +{ + QMarginsF margins(left, top, right, bottom); + if (m_margins == margins) + return; + m_margins = margins; + markDirty(DirtyGeometry); +} + +void QSGOpenVGNinePatchNode::update() +{ + +} + +void QSGOpenVGNinePatchNode::render() +{ + if (!m_texture) + return; + + // Set Draw Mode + if (opacity() < 1.0) { + //Transparent + vgSetPaint(opacityPaint(), VG_FILL_PATH); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); + } else { + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + } + + VGImage image = static_cast<VGImage>(m_texture->textureId()); + + //Draw borderImage + QSGOpenVGHelpers::qDrawBorderImage(image, m_texture->textureSize(), m_bounds, m_bounds.marginsRemoved(m_margins), QRectF(0, 0, 1, 1)); +} + +QRectF QSGOpenVGNinePatchNode::bounds() const +{ + return m_bounds; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h new file mode 100644 index 0000000000..70b087e9fc --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgpublicnodes.h @@ -0,0 +1,143 @@ +#ifndef QSGOPENVGPUBLICNODES_H +#define QSGOPENVGPUBLICNODES_H + +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtQuick/qsgrectanglenode.h> +#include <QtQuick/qsgimagenode.h> +#include <QtQuick/qsgninepatchnode.h> + +#include <QtGui/QPixmap> + +#include <VG/openvg.h> + +#include "qsgopenvgrenderable.h" + +QT_BEGIN_NAMESPACE + +class QSGOpenVGRectangleNode : public QSGRectangleNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGRectangleNode(); + ~QSGOpenVGRectangleNode(); + + void setRect(const QRectF &rect) override; + QRectF rect() const override { return m_rect; } + + void setColor(const QColor &color) override; + QColor color() const override { return m_color; } + + void render() override; + +private: + QRectF m_rect; + QColor m_color; + + + bool m_pathDirty = true; + bool m_paintDirty = true; + + VGPath m_rectPath; + VGPaint m_rectPaint; +}; + +class QSGOpenVGImageNode : public QSGImageNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGImageNode(); + ~QSGOpenVGImageNode(); + + void setRect(const QRectF &rect) override { m_rect = rect; markDirty(DirtyMaterial); } + QRectF rect() const override { return m_rect; } + + void setSourceRect(const QRectF &r) override { m_sourceRect = r; } + QRectF sourceRect() const override { return m_sourceRect; } + + void setTexture(QSGTexture *texture) override; + QSGTexture *texture() const override { return m_texture; } + + void setFiltering(QSGTexture::Filtering filtering) override { m_filtering = filtering; markDirty(DirtyMaterial); } + QSGTexture::Filtering filtering() const override { return m_filtering; } + + void setMipmapFiltering(QSGTexture::Filtering) override { } + QSGTexture::Filtering mipmapFiltering() const override { return QSGTexture::None; } + + void setTextureCoordinatesTransform(TextureCoordinatesTransformMode transformNode) override; + TextureCoordinatesTransformMode textureCoordinatesTransform() const override { return m_transformMode; } + + void setOwnsTexture(bool owns) override { m_owns = owns; } + bool ownsTexture() const override { return m_owns; } + + void render() override; + +private: + QSGTexture *m_texture; + QRectF m_rect; + QRectF m_sourceRect; + bool m_owns; + QSGTexture::Filtering m_filtering; + TextureCoordinatesTransformMode m_transformMode; +}; + +class QSGOpenVGNinePatchNode : public QSGNinePatchNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGNinePatchNode(); + + void setTexture(QSGTexture *texture) override; + void setBounds(const QRectF &bounds) override; + void setDevicePixelRatio(qreal ratio) override; + void setPadding(qreal left, qreal top, qreal right, qreal bottom) override; + void update() override; + + void render() override; + + QRectF bounds() const; + +private: + QSGTexture *m_texture; + QRectF m_bounds; + qreal m_pixelRatio; + QMarginsF m_margins; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGPUBLICNODES_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderable.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderable.cpp new file mode 100644 index 0000000000..0856acfc9a --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderable.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgrenderable.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGRenderable::QSGOpenVGRenderable() + : m_opacity(1.0f) +{ + m_opacityPaint = vgCreatePaint(); +} + +QSGOpenVGRenderable::~QSGOpenVGRenderable() +{ + vgDestroyPaint(m_opacityPaint); +} + +void QSGOpenVGRenderable::setOpacity(float opacity) +{ + if (m_opacity == opacity) + return; + + m_opacity = opacity; + VGfloat values[] = { + 1.0f, 1.0f, 1.0f, m_opacity + }; + vgSetParameterfv(m_opacityPaint, VG_PAINT_COLOR, 4, values); +} + +float QSGOpenVGRenderable::opacity() const +{ + return m_opacity; +} + +VGPaint QSGOpenVGRenderable::opacityPaint() const +{ + return m_opacityPaint; +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderable.h b/src/plugins/scenegraph/openvg/qsgopenvgrenderable.h new file mode 100644 index 0000000000..7a09f2afbe --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderable.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGRENDERABLE_H +#define QSGOPENVGRENDERABLE_H + +#include <QtGlobal> + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGRenderable +{ +public: + QSGOpenVGRenderable(); + virtual ~QSGOpenVGRenderable(); + + virtual void render() = 0; + + virtual void setOpacity(float opacity); + float opacity() const; + VGPaint opacityPaint() const; + +private: + float m_opacity; + VGPaint m_opacityPaint; + +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGRENDERABLE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderer.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderer.cpp new file mode 100644 index 0000000000..acd4cf88dc --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderer.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgrenderer_p.h" +#include "qsgopenvgcontext_p.h" +#include "qsgopenvgnodevisitor.h" +#include "qopenvgcontext_p.h" +#include "qsgopenvghelpers.h" + +#include <QtGui/QWindow> + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +QSGOpenVGRenderer::QSGOpenVGRenderer(QSGRenderContext *context) + : QSGRenderer(context) +{ + +} + +QSGOpenVGRenderer::~QSGOpenVGRenderer() +{ + +} + +void QSGOpenVGRenderer::renderScene(uint fboId) +{ + Q_UNUSED(fboId) + class B : public QSGBindable + { + public: + void bind() const { } + } bindable; + QSGRenderer::renderScene(bindable); +} + +void QSGOpenVGRenderer::render() +{ + //Clear the window geometry with the clear color + vgSetfv(VG_CLEAR_COLOR, 4, QSGOpenVGHelpers::qColorToVGColor(clearColor()).constData()); + vgClear(0, 0, VG_MAXINT, VG_MAXINT); + + // Visit each node to render scene + QSGOpenVGNodeVisitor rendererVisitor; + rendererVisitor.visitChildren(rootNode()); +} + +void QSGOpenVGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state) +{ + QSGRenderer::nodeChanged(node, state); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderer_p.h b/src/plugins/scenegraph/openvg/qsgopenvgrenderer_p.h new file mode 100644 index 0000000000..24cabd1b89 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderer_p.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGRENDERER_H +#define QSGOPENVGRENDERER_H + +#include <private/qsgrenderer_p.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGRenderer : public QSGRenderer +{ +public: + QSGOpenVGRenderer(QSGRenderContext *context); + virtual ~QSGOpenVGRenderer(); + + void nodeChanged(QSGNode *node, QSGNode::DirtyState state) override; + + void renderScene(uint fboId = 0) final; + void render() final; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGRENDERER_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp new file mode 100644 index 0000000000..290ee8028c --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop.cpp @@ -0,0 +1,257 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgrenderloop_p.h" +#include "qsgopenvgcontext_p.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QElapsedTimer> + +#include <private/qquickwindow_p.h> +#include <private/qquickprofiler_p.h> + +#include "qopenvgcontext_p.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGRenderLoop::QSGOpenVGRenderLoop() + : vg(nullptr) +{ + sg = QSGContext::createDefaultContext(); + rc = sg->createRenderContext(); +} + +QSGOpenVGRenderLoop::~QSGOpenVGRenderLoop() +{ + delete rc; + delete sg; +} + +void QSGOpenVGRenderLoop::show(QQuickWindow *window) +{ + WindowData data; + data.updatePending = false; + data.grabOnly = false; + m_windows[window] = data; + + maybeUpdate(window); +} + +void QSGOpenVGRenderLoop::hide(QQuickWindow *window) +{ + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); + cd->fireAboutToStop(); +} + +void QSGOpenVGRenderLoop::windowDestroyed(QQuickWindow *window) +{ + m_windows.remove(window); + hide(window); + + QQuickWindowPrivate *d = QQuickWindowPrivate::get(window); + d->cleanupNodesOnShutdown(); + + if (m_windows.size() == 0) { + rc->invalidate(); + delete vg; + vg = nullptr; + QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); + } else if (vg && window == vg->window()) { + vg->doneCurrent(); + } +} + +void QSGOpenVGRenderLoop::exposureChanged(QQuickWindow *window) +{ + if (window->isExposed()) { + m_windows[window].updatePending = true; + renderWindow(window); + } +} + +QImage QSGOpenVGRenderLoop::grab(QQuickWindow *window) +{ + if (!m_windows.contains(window)) + return QImage(); + + m_windows[window].grabOnly = true; + + renderWindow(window); + + QImage grabbed = grabContent; + grabContent = QImage(); + return grabbed; +} + +void QSGOpenVGRenderLoop::update(QQuickWindow *window) +{ + maybeUpdate(window); +} + +void QSGOpenVGRenderLoop::handleUpdateRequest(QQuickWindow *window) +{ + renderWindow(window); +} + +void QSGOpenVGRenderLoop::maybeUpdate(QQuickWindow *window) +{ + if (!m_windows.contains(window)) + return; + + m_windows[window].updatePending = true; + window->requestUpdate(); +} + +QAnimationDriver *QSGOpenVGRenderLoop::animationDriver() const +{ + return nullptr; +} + +QSGContext *QSGOpenVGRenderLoop::sceneGraphContext() const +{ + return sg; +} + +QSGRenderContext *QSGOpenVGRenderLoop::createRenderContext(QSGContext *) const +{ + return rc; +} + +void QSGOpenVGRenderLoop::releaseResources(QQuickWindow *window) +{ + Q_UNUSED(window) +} + +QSurface::SurfaceType QSGOpenVGRenderLoop::windowSurfaceType() const +{ + return QSurface::OpenVGSurface; +} + +void QSGOpenVGRenderLoop::renderWindow(QQuickWindow *window) +{ + QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window); + if (!cd->isRenderable() || !m_windows.contains(window)) + return; + + WindowData &data = const_cast<WindowData &>(m_windows[window]); + + if (vg == nullptr) { + vg = new QOpenVGContext(window); + vg->makeCurrent(); + cd->context->initialize(vg); + } else { + vg->makeCurrent(); + } + + bool alsoSwap = data.updatePending; + data.updatePending = false; + + if (!data.grabOnly) { + // Event delivery/processing triggered the window to be deleted or stop rendering. + if (!m_windows.contains(window)) + return; + } + QElapsedTimer renderTimer; + qint64 renderTime = 0, syncTime = 0, polishTime = 0; + bool profileFrames = QSG_OPENVG_LOG_TIME_RENDERLOOP().isDebugEnabled(); + if (profileFrames) + renderTimer.start(); + Q_QUICK_SG_PROFILE_START(QQuickProfiler::SceneGraphPolishFrame); + + cd->polishItems(); + + if (profileFrames) + polishTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_SWITCH(QQuickProfiler::SceneGraphPolishFrame, + QQuickProfiler::SceneGraphRenderLoopFrame); + + emit window->afterAnimating(); + + cd->syncSceneGraph(); + + if (profileFrames) + syncTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame); + + // setup coordinate system for window + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadIdentity(); + vgTranslate(0.0f, window->size().height()); + vgScale(1.0, -1.0); + + cd->renderSceneGraph(window->size()); + + if (profileFrames) + renderTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_RECORD(QQuickProfiler::SceneGraphRenderLoopFrame); + + if (data.grabOnly) { + grabContent = vg->readFramebuffer(window->size() * window->effectiveDevicePixelRatio()); + data.grabOnly = false; + } + + if (alsoSwap && window->isVisible()) { + vg->swapBuffers(); + cd->fireFrameSwapped(); + } + + qint64 swapTime = 0; + if (profileFrames) + swapTime = renderTimer.nsecsElapsed(); + Q_QUICK_SG_PROFILE_END(QQuickProfiler::SceneGraphRenderLoopFrame); + + if (QSG_OPENVG_LOG_TIME_RENDERLOOP().isDebugEnabled()) { + static QTime lastFrameTime = QTime::currentTime(); + qCDebug(QSG_OPENVG_LOG_TIME_RENDERLOOP, + "Frame rendered with 'basic' renderloop in %dms, polish=%d, sync=%d, render=%d, swap=%d, frameDelta=%d", + int(swapTime / 1000000), + int(polishTime / 1000000), + int((syncTime - polishTime) / 1000000), + int((renderTime - syncTime) / 1000000), + int((swapTime - renderTime) / 10000000), + int(lastFrameTime.msecsTo(QTime::currentTime()))); + lastFrameTime = QTime::currentTime(); + } + + // Might have been set during syncSceneGraph() + if (data.updatePending) + maybeUpdate(window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgrenderloop_p.h b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop_p.h new file mode 100644 index 0000000000..f35b689e00 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgrenderloop_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGRENDERLOOP_H +#define QSGOPENVGRENDERLOOP_H + +#include <private/qsgrenderloop_p.h> + +QT_BEGIN_NAMESPACE + +class QOpenVGContext; + +class QSGOpenVGRenderLoop : public QSGRenderLoop +{ +public: + QSGOpenVGRenderLoop(); + ~QSGOpenVGRenderLoop(); + + + void show(QQuickWindow *window) override; + void hide(QQuickWindow *window) override; + + void windowDestroyed(QQuickWindow *window) override; + + void renderWindow(QQuickWindow *window); + void exposureChanged(QQuickWindow *window) override; + QImage grab(QQuickWindow *window) override; + + void maybeUpdate(QQuickWindow *window) override; + void update(QQuickWindow *window) override; + void handleUpdateRequest(QQuickWindow *window) override; + + void releaseResources(QQuickWindow *) override; + + QSurface::SurfaceType windowSurfaceType() const override; + + QAnimationDriver *animationDriver() const override; + + QSGContext *sceneGraphContext() const override; + QSGRenderContext *createRenderContext(QSGContext *) const override; + + struct WindowData { + bool updatePending : 1; + bool grabOnly : 1; + }; + + QHash<QQuickWindow *, WindowData> m_windows; + + QSGContext *sg; + QSGRenderContext *rc; + QOpenVGContext *vg; + + QImage grabContent; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGRENDERLOOP_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp new file mode 100644 index 0000000000..9bce12c83f --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgspritenode.h" +#include "qsgopenvgtexture.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGSpriteNode::QSGOpenVGSpriteNode() + : m_time(0.0f) +{ + // Set Dummy material and geometry to avoid asserts + setMaterial((QSGMaterial*)1); + setGeometry((QSGGeometry*)1); +} + +QSGOpenVGSpriteNode::~QSGOpenVGSpriteNode() +{ + +} + +void QSGOpenVGSpriteNode::setTexture(QSGTexture *texture) +{ + m_texture = static_cast<QSGOpenVGTexture*>(texture); + markDirty(DirtyMaterial); +} + +void QSGOpenVGSpriteNode::setTime(float time) +{ + if (m_time != time) { + m_time = time; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGSpriteNode::setSourceA(const QPoint &source) +{ + if (m_sourceA != source) { + m_sourceA = source; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGSpriteNode::setSourceB(const QPoint &source) +{ + if (m_sourceB != source) { + m_sourceB = source; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGSpriteNode::setSpriteSize(const QSize &size) +{ + if (m_spriteSize != size) { + m_spriteSize = size; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGSpriteNode::setSheetSize(const QSize &size) +{ + if (m_sheetSize != size) { + m_sheetSize = size; + markDirty(DirtyMaterial); + } +} + +void QSGOpenVGSpriteNode::setSize(const QSizeF &size) +{ + if (m_size != size) { + m_size = size; + markDirty(DirtyGeometry); + } +} + +void QSGOpenVGSpriteNode::setFiltering(QSGTexture::Filtering) +{ +} + +void QSGOpenVGSpriteNode::update() +{ +} + +void QSGOpenVGSpriteNode::render() +{ + if (!m_texture) + return; + + VGImage image = static_cast<VGImage>(m_texture->textureId()); + + QRectF sourceRect(m_sourceA, m_spriteSize); + QRectF targetRect(0, 0, m_size.width(), m_size.height()); + + VGImage sourceImage = vgChildImage(image, sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height()); + + // Set Draw Mode + if (opacity() < 1.0) { + //Transparent + vgSetPaint(opacityPaint(), VG_FILL_PATH); + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY); + } else { + vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL); + } + + if (sourceRect != targetRect) { + // Scale + float scaleX = targetRect.width() / sourceRect.width(); + float scaleY = targetRect.height() / sourceRect.height(); + vgScale(scaleX, scaleY); + } + + vgDrawImage(sourceImage); + + vgDestroyImage(sourceImage); +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h new file mode 100644 index 0000000000..3ade2ef8ad --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgspritenode.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGSPRITENODE_H +#define QSGOPENVGSPRITENODE_H + +#include <private/qsgadaptationlayer_p.h> +#include "qsgopenvgrenderable.h" + +QT_BEGIN_NAMESPACE +class QSGOpenVGTexture; +class QSGOpenVGSpriteNode : public QSGSpriteNode, public QSGOpenVGRenderable +{ +public: + QSGOpenVGSpriteNode(); + ~QSGOpenVGSpriteNode(); + + void setTexture(QSGTexture *texture) override; + void setTime(float time) override; + void setSourceA(const QPoint &source) override; + void setSourceB(const QPoint &source) override; + void setSpriteSize(const QSize &size) override; + void setSheetSize(const QSize &size) override; + void setSize(const QSizeF &size) override; + void setFiltering(QSGTexture::Filtering filtering) override; + void update() override; + + void render() override; + +private: + QSGOpenVGTexture *m_texture; + float m_time; + QPoint m_sourceA; + QPoint m_sourceB; + QSize m_spriteSize; + QSize m_sheetSize; + QSizeF m_size; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGSPRITENODE_H diff --git a/src/plugins/scenegraph/openvg/qsgopenvgtexture.cpp b/src/plugins/scenegraph/openvg/qsgopenvgtexture.cpp new file mode 100644 index 0000000000..dd2fdc7020 --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgtexture.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qsgopenvgtexture.h" +#include "qsgopenvghelpers.h" + +QT_BEGIN_NAMESPACE + +QSGOpenVGTexture::QSGOpenVGTexture(const QImage &image, uint flags) +{ + Q_UNUSED(flags) + + VGImageFormat format = QSGOpenVGHelpers::qImageFormatToVGImageFormat(image.format()); + m_image = vgCreateImage(format, image.width(), image.height(), VG_IMAGE_QUALITY_BETTER); + + // Do Texture Upload + vgImageSubData(m_image, image.constBits(), image.bytesPerLine(), format, 0, 0, image.width(), image.height()); +} + +QSGOpenVGTexture::~QSGOpenVGTexture() +{ + vgDestroyImage(m_image); +} + +int QSGOpenVGTexture::textureId() const +{ + return static_cast<int>(m_image); +} + +QSize QSGOpenVGTexture::textureSize() const +{ + VGint imageWidth = vgGetParameteri(m_image, VG_IMAGE_WIDTH); + VGint imageHeight = vgGetParameteri(m_image, VG_IMAGE_HEIGHT); + return QSize(imageWidth, imageHeight); +} + +bool QSGOpenVGTexture::hasAlphaChannel() const +{ + VGImageFormat format = static_cast<VGImageFormat>(vgGetParameteri(m_image, VG_IMAGE_FORMAT)); + + switch (format) { + case VG_sRGBA_8888: + case VG_sRGBA_8888_PRE: + case VG_sRGBA_5551: + case VG_sRGBA_4444: + case VG_lRGBA_8888: + case VG_lRGBA_8888_PRE: + case VG_A_8: + case VG_A_1: + case VG_A_4: + case VG_sARGB_8888: + case VG_sARGB_8888_PRE: + case VG_sARGB_1555: + case VG_sARGB_4444: + case VG_lARGB_8888: + case VG_lARGB_8888_PRE: + case VG_sBGRA_8888: + case VG_sBGRA_8888_PRE: + case VG_sBGRA_5551: + case VG_sBGRA_4444: + case VG_lBGRA_8888: + case VG_lBGRA_8888_PRE: + case VG_sABGR_8888: + case VG_sABGR_8888_PRE: + case VG_sABGR_1555: + case VG_sABGR_4444: + case VG_lABGR_8888: + case VG_lABGR_8888_PRE: + return true; + break; + default: + break; + } + return false; +} + +bool QSGOpenVGTexture::hasMipmaps() const +{ + return false; +} + +void QSGOpenVGTexture::bind() +{ + // No need to bind +} + +QT_END_NAMESPACE diff --git a/src/plugins/scenegraph/openvg/qsgopenvgtexture.h b/src/plugins/scenegraph/openvg/qsgopenvgtexture.h new file mode 100644 index 0000000000..523c9e690d --- /dev/null +++ b/src/plugins/scenegraph/openvg/qsgopenvgtexture.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQuick module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QSGOPENVGTEXTURE_H +#define QSGOPENVGTEXTURE_H + +#include <private/qsgtexture_p.h> + +#include <VG/openvg.h> + +QT_BEGIN_NAMESPACE + +class QSGOpenVGTexture : public QSGTexture +{ +public: + QSGOpenVGTexture(const QImage &image, uint flags); + ~QSGOpenVGTexture(); + + int textureId() const override; + QSize textureSize() const override; + bool hasAlphaChannel() const override; + bool hasMipmaps() const override; + void bind() override; + +private: + VGImage m_image;; +}; + +QT_END_NAMESPACE + +#endif // QSGOPENVGTEXTURE_H diff --git a/src/plugins/scenegraph/scenegraph.pro b/src/plugins/scenegraph/scenegraph.pro index a90e8d4814..39c0c0815c 100644 --- a/src/plugins/scenegraph/scenegraph.pro +++ b/src/plugins/scenegraph/scenegraph.pro @@ -1,3 +1,5 @@ TEMPLATE = subdirs QT_FOR_CONFIG += quick qtConfig(d3d12): SUBDIRS += d3d12 +qtConfig(openvg): SUBDIRS += openvg + |