1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2017 The Qt Company Ltd. |
4 | ** Copyright (C) 2017 Mapbox, Inc. |
5 | ** Contact: http://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the QtLocation module of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:LGPL3$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see http://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at http://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU Lesser General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the |
22 | ** packaging of this file. Please review the following information to |
23 | ** ensure the GNU Lesser General Public License version 3 requirements |
24 | ** will be met: https://www.gnu.org/licenses/lgpl.html. |
25 | ** |
26 | ** GNU General Public License Usage |
27 | ** Alternatively, this file may be used under the terms of the GNU |
28 | ** General Public License version 2.0 or later as published by the Free |
29 | ** Software Foundation and appearing in the file LICENSE.GPL included in |
30 | ** the packaging of this file. Please review the following information to |
31 | ** ensure the GNU General Public License version 2.0 requirements will be |
32 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. |
33 | ** |
34 | ** $QT_END_LICENSE$ |
35 | ** |
36 | ****************************************************************************/ |
37 | |
38 | #include "qsgmapboxglnode.h" |
39 | #include "qgeomapmapboxgl.h" |
40 | |
41 | #if QT_HAS_INCLUDE(<QtQuick/private/qsgplaintexture_p.h>) |
42 | #include <QtQuick/private/qsgplaintexture_p.h> |
43 | #endif |
44 | |
45 | #include <QtGui/QOpenGLContext> |
46 | #include <QtGui/QOpenGLFunctions> |
47 | |
48 | // QSGMapboxGLTextureNode |
49 | |
50 | static const QSize minTextureSize = QSize(64, 64); |
51 | |
52 | QSGMapboxGLTextureNode::QSGMapboxGLTextureNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap) |
53 | : QSGSimpleTextureNode() |
54 | { |
55 | setTextureCoordinatesTransform(QSGSimpleTextureNode::MirrorVertically); |
56 | setFiltering(QSGTexture::Linear); |
57 | |
58 | m_map.reset(other: new QMapboxGL(nullptr, settings, size.expandedTo(otherSize: minTextureSize), pixelRatio)); |
59 | |
60 | QObject::connect(sender: m_map.data(), signal: &QMapboxGL::needsRendering, receiver: geoMap, slot: &QGeoMap::sgNodeChanged); |
61 | QObject::connect(sender: m_map.data(), signal: &QMapboxGL::copyrightsChanged, receiver: geoMap, |
62 | slot: static_cast<void (QGeoMap::*)(const QString &)>(&QGeoMapMapboxGL::copyrightsChanged)); |
63 | } |
64 | |
65 | void QSGMapboxGLTextureNode::resize(const QSize &size, qreal pixelRatio) |
66 | { |
67 | const QSize& minSize = size.expandedTo(otherSize: minTextureSize); |
68 | const QSize fbSize = minSize * pixelRatio; |
69 | m_map->resize(size: minSize); |
70 | |
71 | m_fbo.reset(other: new QOpenGLFramebufferObject(fbSize, QOpenGLFramebufferObject::CombinedDepthStencil)); |
72 | m_map->setFramebufferObject(fbo: m_fbo->handle(), size: fbSize); |
73 | |
74 | QSGPlainTexture *fboTexture = static_cast<QSGPlainTexture *>(texture()); |
75 | if (!fboTexture) { |
76 | fboTexture = new QSGPlainTexture; |
77 | fboTexture->setHasAlphaChannel(true); |
78 | } |
79 | |
80 | fboTexture->setTextureId(m_fbo->texture()); |
81 | fboTexture->setTextureSize(fbSize); |
82 | |
83 | if (!texture()) { |
84 | setTexture(fboTexture); |
85 | setOwnsTexture(true); |
86 | } |
87 | |
88 | setRect(QRectF(QPointF(), minSize)); |
89 | markDirty(bits: QSGNode::DirtyGeometry); |
90 | } |
91 | |
92 | void QSGMapboxGLTextureNode::render(QQuickWindow *window) |
93 | { |
94 | QOpenGLFunctions *f = window->openglContext()->functions(); |
95 | f->glViewport(x: 0, y: 0, width: m_fbo->width(), height: m_fbo->height()); |
96 | |
97 | GLint alignment; |
98 | f->glGetIntegerv(GL_UNPACK_ALIGNMENT, params: &alignment); |
99 | |
100 | m_fbo->bind(); |
101 | |
102 | f->glClearColor(red: 0.f, green: 0.f, blue: 0.f, alpha: 0.f); |
103 | f->glColorMask(red: true, green: true, blue: true, alpha: true); |
104 | f->glClear(GL_COLOR_BUFFER_BIT); |
105 | |
106 | m_map->render(); |
107 | m_fbo->release(); |
108 | |
109 | // QTBUG-62861 |
110 | f->glPixelStorei(GL_UNPACK_ALIGNMENT, param: alignment); |
111 | |
112 | window->resetOpenGLState(); |
113 | markDirty(bits: QSGNode::DirtyMaterial); |
114 | } |
115 | |
116 | QMapboxGL* QSGMapboxGLTextureNode::map() const |
117 | { |
118 | return m_map.data(); |
119 | } |
120 | |
121 | // QSGMapboxGLRenderNode |
122 | |
123 | QSGMapboxGLRenderNode::QSGMapboxGLRenderNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap) |
124 | : QSGRenderNode() |
125 | { |
126 | m_map.reset(other: new QMapboxGL(nullptr, settings, size, pixelRatio)); |
127 | QObject::connect(sender: m_map.data(), signal: &QMapboxGL::needsRendering, receiver: geoMap, slot: &QGeoMap::sgNodeChanged); |
128 | QObject::connect(sender: m_map.data(), signal: &QMapboxGL::copyrightsChanged, receiver: geoMap, |
129 | slot: static_cast<void (QGeoMap::*)(const QString &)>(&QGeoMapMapboxGL::copyrightsChanged)); |
130 | } |
131 | |
132 | QMapboxGL* QSGMapboxGLRenderNode::map() const |
133 | { |
134 | return m_map.data(); |
135 | } |
136 | |
137 | void QSGMapboxGLRenderNode::render(const RenderState *state) |
138 | { |
139 | // QMapboxGL assumes we've prepared the viewport prior to render(). |
140 | QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions(); |
141 | f->glViewport(x: state->scissorRect().x(), y: state->scissorRect().y(), width: state->scissorRect().width(), height: state->scissorRect().height()); |
142 | f->glScissor(x: state->scissorRect().x(), y: state->scissorRect().y(), width: state->scissorRect().width(), height: state->scissorRect().height()); |
143 | f->glEnable(GL_SCISSOR_TEST); |
144 | |
145 | GLint alignment; |
146 | f->glGetIntegerv(GL_UNPACK_ALIGNMENT, params: &alignment); |
147 | |
148 | m_map->render(); |
149 | |
150 | // QTBUG-62861 |
151 | f->glPixelStorei(GL_UNPACK_ALIGNMENT, param: alignment); |
152 | } |
153 | |
154 | QSGRenderNode::StateFlags QSGMapboxGLRenderNode::changedStates() const |
155 | { |
156 | return QSGRenderNode::DepthState |
157 | | QSGRenderNode::StencilState |
158 | | QSGRenderNode::ScissorState |
159 | | QSGRenderNode::ColorState |
160 | | QSGRenderNode::BlendState |
161 | | QSGRenderNode::ViewportState |
162 | | QSGRenderNode::RenderTargetState; |
163 | } |
164 | |
165 | |