1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the Qt WebGL module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 or (at your option) any later version
20** approved by the KDE Free Qt Foundation. The licenses are as published by
21** the Free Software Foundation and appearing in the file LICENSE.GPL3
22** included in the packaging of this file. Please review the following
23** information to ensure the GNU General Public License requirements will
24** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25**
26** $QT_END_LICENSE$
27**
28****************************************************************************/
29
30#include "qwebglwindow.h"
31#include "qwebglwindow_p.h"
32
33#include "qwebglintegration_p.h"
34#include "qwebglwebsocketserver.h"
35
36#include <QtCore/qtextstream.h>
37#include <QtGui/private/qguiapplication_p.h>
38#include <QtGui/private/qopenglcontext_p.h>
39#include <QtGui/private/qwindow_p.h>
40#include <QtGui/qpa/qwindowsysteminterface.h>
41#include <QtGui/qpa/qplatformintegration.h>
42#include <QtGui/qopenglcontext.h>
43#include <QtGui/qoffscreensurface.h>
44
45#include "qwebglwindow.h"
46
47QT_BEGIN_NAMESPACE
48
49static Q_LOGGING_CATEGORY(lc, "qt.qpa.webgl.window")
50
51QAtomicInt QWebGLWindowPrivate::nextId(1);
52
53QWebGLWindowPrivate::QWebGLWindowPrivate(QWebGLWindow *p) :
54 q_ptr(p)
55{}
56
57QWebGLWindow::QWebGLWindow(QWindow *w) :
58 QPlatformWindow(w),
59 d_ptr(new QWebGLWindowPrivate(this))
60{
61}
62
63QWebGLWindow::~QWebGLWindow()
64{
65 destroy();
66}
67
68void QWebGLWindow::create()
69{
70 Q_D(QWebGLWindow);
71 if (d->flags.testFlag(flag: QWebGLWindowPrivate::Created))
72 return;
73
74 d->id = QWebGLWindowPrivate::nextId.fetchAndAddAcquire(valueToAdd: 1);
75 qCDebug(lc, "Window %d created", d->id);
76
77 // Save the original surface type before changing to OpenGLSurface.
78 d->raster = (window()->surfaceType() == QSurface::RasterSurface);
79 if (d->raster) // change to OpenGL, but not for RasterGLSurface
80 window()->setSurfaceType(QSurface::OpenGLSurface);
81
82 if (window()->windowState() == Qt::WindowFullScreen) {
83 QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
84 QPlatformWindow::setGeometry(fullscreenRect);
85 QWindowSystemInterface::handleGeometryChange(window: window(), newRect: fullscreenRect);
86 return;
87 }
88
89 d->flags = QWebGLWindowPrivate::Created;
90
91 if (window()->type() == Qt::Desktop)
92 return;
93
94 d->flags |= QWebGLWindowPrivate::HasNativeWindow;
95 setGeometry(window()->geometry()); // will become fullscreen
96 QWindowSystemInterface::handleExposeEvent(window: window(), region: QRect(QPoint(0, 0), geometry().size()));
97
98 if (d->raster) {
99 QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
100 context->setShareContext(qt_gl_global_share_context());
101 context->setFormat(d->format);
102 context->setScreen(window()->screen());
103 if (Q_UNLIKELY(!context->create()))
104 qFatal(msg: "QWebGL: Failed to create compositing context");
105 }
106}
107
108void QWebGLWindow::destroy()
109{
110 Q_D(QWebGLWindow);
111 qCDebug(lc, "Destroying %d", d->id);
112 if (d->flags.testFlag(flag: QWebGLWindowPrivate::HasNativeWindow)) {
113 invalidateSurface();
114 }
115
116 qt_window_private(window: window())->updateRequestPending = false;
117
118 d->flags = QWebGLWindowPrivate::Flags{};
119
120 auto integrationPrivate = QWebGLIntegrationPrivate::instance();
121 auto clientData = integrationPrivate->findClientData(surface: surface()->surfaceHandle());
122 if (clientData) {
123 const QVariantMap values {
124 { "winId", winId() }
125 };
126 if (clientData->socket)
127 integrationPrivate->sendMessage(socket: clientData->socket,
128 type: QWebGLWebSocketServer::MessageType::DestroyCanvas,
129 values);
130 clientData->platformWindows.removeAll(t: this);
131 }
132}
133
134void QWebGLWindow::raise()
135{
136 QWindow *wnd = window();
137 if (wnd->type() != Qt::Desktop) {
138 QWindowSystemInterface::handleExposeEvent(window: wnd, region: QRect(QPoint(0, 0), wnd->geometry().size()));
139 }
140}
141
142QSurfaceFormat QWebGLWindow::format() const
143{
144 Q_D(const QWebGLWindow);
145 return d->format;
146}
147
148QWebGLScreen *QWebGLWindow::screen() const
149{
150 return static_cast<QWebGLScreen *>(QPlatformWindow::screen());
151}
152
153void QWebGLWindow::setGeometry(const QRect &rect)
154{
155 QWindowSystemInterface::handleGeometryChange(window: window(), newRect: rect);
156 QPlatformWindow::setGeometry(rect);
157}
158
159void QWebGLWindow::setDefaults(const QMap<GLenum, QVariant> &values)
160{
161 Q_D(QWebGLWindow);
162 d->defaults.set_value(values);
163}
164
165WId QWebGLWindow::winId() const
166{
167 Q_D(const QWebGLWindow);
168 return d->id;
169}
170
171QWebGLOffscreenSurface::QWebGLOffscreenSurface(QOffscreenSurface *offscreenSurface)
172 : QPlatformOffscreenSurface(offscreenSurface)
173{
174}
175
176QSurfaceFormat QWebGLOffscreenSurface::format() const
177{
178 return offscreenSurface()->format();
179}
180
181bool QWebGLOffscreenSurface::isValid() const
182{
183 return true;
184}
185
186QT_END_NAMESPACE
187

source code of qtwebglplugin/src/plugins/platforms/webgl/qwebglwindow.cpp