1// Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
2// Copyright (C) 2017 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
4
5#include <QtQml/QQmlEngine>
6#include <QQuickWindow>
7#if QT_CONFIG(opengl)
8# include <QOpenGLTextureBlitter>
9# include <QOpenGLTexture>
10# include <QOpenGLFramebufferObject>
11#endif
12#include <QMatrix4x4>
13#include <QRunnable>
14
15#include "qwaylandclient.h"
16#include "qwaylandquickcompositor.h"
17#include "qwaylandquicksurface.h"
18#include "qwaylandquickoutput.h"
19#include "qwaylandquickitem.h"
20#include "qwaylandoutput.h"
21#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
22#include <QtWaylandCompositor/QWaylandViewporter>
23#include "qwaylandsurfacegrabber.h"
24
25QT_BEGIN_NAMESPACE
26
27class QWaylandQuickCompositorPrivate : public QWaylandCompositorPrivate
28{
29public:
30 explicit QWaylandQuickCompositorPrivate(QWaylandCompositor *compositor)
31 : QWaylandCompositorPrivate(compositor)
32 , m_viewporter(new QWaylandViewporter(compositor))
33 {
34 }
35protected:
36 QWaylandSurface *createDefaultSurface() override
37 {
38 return new QWaylandQuickSurface();
39 }
40private:
41 QScopedPointer<QWaylandViewporter> m_viewporter;
42};
43
44QWaylandQuickCompositor::QWaylandQuickCompositor(QObject *parent)
45 : QWaylandCompositor(*new QWaylandQuickCompositorPrivate(this), parent)
46{
47}
48
49/*!
50 * \qmlproperty list QtWayland.Compositor::WaylandCompositor::extensions
51 *
52 * A list of extensions that the compositor advertises to its clients. For
53 * any Wayland extension the compositor should support, instantiate its component,
54 * and add it to the list of extensions.
55 *
56 * For instance, the following code would allow the clients to request \c wl_shell
57 * surfaces in the compositor using the \c wl_shell interface.
58 *
59 * \qml
60 * import QtWayland.Compositor
61 *
62 * WaylandCompositor {
63 * WlShell {
64 * // ...
65 * }
66 * }
67 * \endqml
68 */
69
70void QWaylandQuickCompositor::create()
71{
72 QWaylandCompositor::create();
73}
74
75
76void QWaylandQuickCompositor::classBegin()
77{
78 QWaylandCompositorPrivate::get(compositor: this)->preInit();
79}
80
81void QWaylandQuickCompositor::componentComplete()
82{
83 create();
84}
85
86/*!
87 * Grab the surface content from the given \a buffer.
88 * Reimplemented from QWaylandCompositor::grabSurface.
89 */
90void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWaylandBufferRef &buffer)
91{
92 if (buffer.isSharedMemory()) {
93 QWaylandCompositor::grabSurface(grabber, buffer);
94 return;
95 }
96
97#if QT_CONFIG(opengl)
98 QWaylandQuickOutput *output = static_cast<QWaylandQuickOutput *>(defaultOutput());
99 if (!output) {
100 emit grabber->failed(error: QWaylandSurfaceGrabber::RendererNotReady);
101 return;
102 }
103
104 // We cannot grab the surface now, we need to have a current opengl context, so we
105 // need to be in the render thread
106 class GrabState : public QRunnable
107 {
108 public:
109 QWaylandSurfaceGrabber *grabber = nullptr;
110 QWaylandBufferRef buffer;
111
112 void run() override
113 {
114 QOpenGLFramebufferObject fbo(buffer.size());
115 fbo.bind();
116 QOpenGLTextureBlitter blitter;
117 blitter.create();
118
119 glViewport(x: 0, y: 0, width: buffer.size().width(), height: buffer.size().height());
120
121 QOpenGLTextureBlitter::Origin surfaceOrigin =
122 buffer.origin() == QWaylandSurface::OriginTopLeft
123 ? QOpenGLTextureBlitter::OriginTopLeft
124 : QOpenGLTextureBlitter::OriginBottomLeft;
125
126 auto texture = buffer.toOpenGLTexture();
127 blitter.bind(target: texture->target());
128 blitter.blit(texture: texture->textureId(), targetTransform: QMatrix4x4(), sourceOrigin: surfaceOrigin);
129 blitter.release();
130
131 emit grabber->success(image: fbo.toImage());
132 }
133 };
134
135 GrabState *state = new GrabState;
136 state->grabber = grabber;
137 state->buffer = buffer;
138 static_cast<QQuickWindow *>(output->window())->scheduleRenderJob(job: state, schedule: QQuickWindow::AfterRenderingStage);
139#else
140 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);
141#endif
142}
143
144QT_END_NAMESPACE
145
146#include "moc_qwaylandquickcompositor.cpp"
147

source code of qtwayland/src/compositor/compositor_api/qwaylandquickcompositor.cpp