8#include <wayland-kms.h>
12#include <private/qwaylandquickhardwarelayer_p.h>
13#include <private/qwaylandquickitem_p.h>
14#include <private/qwaylandview_p.h>
15#include <QWaylandQuickOutput>
16#include <QQuickWindow>
18#include <qpa/qlatformscreen_p.h>
20using namespace QNativeInterface::
Private;
24Vsp2Buffer::Vsp2Buffer(wl_kms_buffer *kmsBuffer)
25 : dmabufFd(kmsBuffer->fd)
26 , bytesPerLine(kmsBuffer->stride)
27 , drmPixelFormat(kmsBuffer->format)
28 , size(kmsBuffer->width, kmsBuffer->height)
35 auto *wlItem = m_hwLayer->waylandItem();
36 m_screen =
dynamic_cast<QVsp2Screen*>(wlItem->window()->screen()->handle());
39 connect(hwLayer, &QWaylandQuickHardwareLayer::stackingLevelChanged,
this, [integration](){
40 integration->recreateVspLayers();
45 hwLayer->setSceneGraphPainting(
false);
46 QWaylandViewPrivate::get(hwLayer->waylandItem()->view())->independentFrameCallback =
true;
52 auto *kmsBuffer = nextKmsBuffer();
57 m_buffer = Vsp2Buffer(kmsBuffer);
60 m_layerIndex = m_screen->addLayer(m_buffer.dmabufFd, m_buffer.size, m_position, m_buffer.drmPixelFormat, m_buffer.bytesPerLine);
62 auto *wlItem = m_hwLayer->waylandItem();
63 wlItem->surface()->frameStarted();
69 m_screen->removeLayer(m_layerIndex);
81 auto *kmsBuffer = nextKmsBuffer();
84 if (m_buffer.dmabufFd != -1) {
85 bool formatChanged =
false;
86 formatChanged |= newBuffer.bytesPerLine != m_buffer.bytesPerLine;
87 formatChanged |= newBuffer.size != m_buffer.size;
88 formatChanged |= newBuffer.drmPixelFormat != m_buffer.drmPixelFormat;
90 qWarning() <<
"The VSP2 Wayland hardware layer integration doesn't support changing"
91 <<
"surface formats, this will most likely fail";
96 m_screen->setLayerBuffer(m_layerIndex, m_buffer.dmabufFd);
98 auto *wlItem = m_hwLayer->waylandItem();
99 wlItem->surface()->frameStarted();
104 auto newSurface = m_hwLayer->waylandItem()->surface();
106 if (Q_UNLIKELY(newSurface == m_surface))
110 disconnect(
this->m_surface, &QWaylandSurface::redraw,
this, &Vsp2Layer::handleBufferCommitted);
112 connect(newSurface, &QWaylandSurface::redraw,
this, &Vsp2Layer::handleBufferCommitted, Qt::DirectConnection);
114 this->m_surface = newSurface;
119 QWaylandQuickItem *wlItem = m_hwLayer->waylandItem();
120 QRectF localGeometry(0, 0, wlItem->width(), wlItem->height());
121 auto lastMatrix = QWaylandQuickItemPrivate::get(wlItem)->lastMatrix;
122 auto globalGeometry = lastMatrix.mapRect(localGeometry);
124 if (m_buffer.size != globalGeometry.size().toSize()) {
125 qWarning() <<
"wl_buffer size != WaylandQuickItem size and scaling has not been"
126 <<
"implemented for the vsp2 hardware layer integration";
129 m_position = globalGeometry.topLeft().toPoint();
131 m_screen->setLayerPosition(m_layerIndex, m_position);
137 qreal opacity = m_hwLayer->waylandItem()->opacity();
138 m_screen->setLayerAlpha(m_layerIndex, opacity);
144 Q_ASSERT(m_hwLayer && m_hwLayer->waylandItem());
145 QWaylandQuickItem *wlItem = m_hwLayer->waylandItem();
146 auto view = wlItem->view();
150 auto wlBuffer = view->currentBuffer().wl_buffer();
155 struct wl_kms_buffer *kmsBuffer = wayland_kms_buffer_get(wlBuffer);
158 qWarning() <<
"Failed to get wl_kms_buffer for wl_buffer:" << wl_resource_get_id(wlBuffer);
165 for (
auto &layer : std::as_const(m_layers)) {
166 Q_ASSERT(!layer->isEnabled());
167 layer->enableVspLayer();
173 for (
auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) {
174 if ((*it)->isEnabled())
175 (*it)->disableVspLayer();
181 std::sort(m_layers.begin(), m_layers.end(), [](
auto &l1,
auto &l2){
182 return l1->hwLayer()->stackingLevel() < l2->hwLayer()->stackingLevel();
194 if (QGuiApplication::platformName() !=
"eglfs") {
195 qWarning() <<
"Vsp2 layers are currently only supported on the eglfs platform plugin"
196 <<
"with the eglfs_kms_vsp2 device integration.\n"
197 <<
"You need to set QT_QPA_PLATFORM=eglfs and QT_QPA_EGLFS_INTEGRATION=eglfs_kms_vsp2";
200 auto screen =
dynamic_cast<QVsp2Screen*>(QGuiApplication::primaryScreen()->handle());
201 screen->addBlendListener([](){
209 m_layers.append(QSharedPointer<Vsp2Layer>(
new Vsp2Layer(hwLayer,
this)));
217 for (
auto it = m_layers.begin(); it != m_layers.end(); ++it) {
218 if ((*it)->hwLayer() == hwLayer) {
228 for (
auto &layer : std::as_const(m_layers)) {
229 if (
auto *surface = layer->hwLayer()->waylandItem()->surface())
230 surface->sendFrameCallbacks();
void sendFrameCallbacks()
void add(QWaylandQuickHardwareLayer *layer) override
void remove(QWaylandQuickHardwareLayer *layer) override
void handleSurfaceChanged()
Vsp2Buffer(wl_kms_buffer *kmsBuffer)