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 
QSGMapboxGLTextureNode(const QMapboxGLSettings & settings,const QSize & size,qreal pixelRatio,QGeoMapMapboxGL * geoMap)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(new QMapboxGL(nullptr, settings, size.expandedTo(minTextureSize), pixelRatio));
59 
60     QObject::connect(m_map.data(), &QMapboxGL::needsRendering, geoMap, &QGeoMap::sgNodeChanged);
61     QObject::connect(m_map.data(), &QMapboxGL::copyrightsChanged, geoMap,
62             static_cast<void (QGeoMap::*)(const QString &)>(&QGeoMapMapboxGL::copyrightsChanged));
63 }
64 
resize(const QSize & size,qreal pixelRatio)65 void QSGMapboxGLTextureNode::resize(const QSize &size, qreal pixelRatio)
66 {
67     const QSize& minSize = size.expandedTo(minTextureSize);
68     const QSize fbSize = minSize * pixelRatio;
69     m_map->resize(minSize);
70 
71     m_fbo.reset(new QOpenGLFramebufferObject(fbSize, QOpenGLFramebufferObject::CombinedDepthStencil));
72     m_map->setFramebufferObject(m_fbo->handle(), 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(QSGNode::DirtyGeometry);
90 }
91 
render(QQuickWindow * window)92 void QSGMapboxGLTextureNode::render(QQuickWindow *window)
93 {
94     QOpenGLFunctions *f = window->openglContext()->functions();
95     f->glViewport(0, 0, m_fbo->width(), m_fbo->height());
96 
97     GLint alignment;
98     f->glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
99 
100     m_fbo->bind();
101 
102     f->glClearColor(0.f, 0.f, 0.f, 0.f);
103     f->glColorMask(true, true, true, 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, alignment);
111 
112     window->resetOpenGLState();
113     markDirty(QSGNode::DirtyMaterial);
114 }
115 
map() const116 QMapboxGL* QSGMapboxGLTextureNode::map() const
117 {
118     return m_map.data();
119 }
120 
121 // QSGMapboxGLRenderNode
122 
QSGMapboxGLRenderNode(const QMapboxGLSettings & settings,const QSize & size,qreal pixelRatio,QGeoMapMapboxGL * geoMap)123 QSGMapboxGLRenderNode::QSGMapboxGLRenderNode(const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio, QGeoMapMapboxGL *geoMap)
124         : QSGRenderNode()
125 {
126     m_map.reset(new QMapboxGL(nullptr, settings, size, pixelRatio));
127     QObject::connect(m_map.data(), &QMapboxGL::needsRendering, geoMap, &QGeoMap::sgNodeChanged);
128     QObject::connect(m_map.data(), &QMapboxGL::copyrightsChanged, geoMap,
129             static_cast<void (QGeoMap::*)(const QString &)>(&QGeoMapMapboxGL::copyrightsChanged));
130 }
131 
map() const132 QMapboxGL* QSGMapboxGLRenderNode::map() const
133 {
134     return m_map.data();
135 }
136 
render(const RenderState * state)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(state->scissorRect().x(), state->scissorRect().y(), state->scissorRect().width(), state->scissorRect().height());
142     f->glScissor(state->scissorRect().x(), state->scissorRect().y(), state->scissorRect().width(), state->scissorRect().height());
143     f->glEnable(GL_SCISSOR_TEST);
144 
145     GLint alignment;
146     f->glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment);
147 
148     m_map->render();
149 
150     // QTBUG-62861
151     f->glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
152 }
153 
changedStates() const154 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