9#include <wayland-kms.h>
13#include <private/qwaylandquickhardwarelayer_p.h>
14#include <private/qwaylandquickitem_p.h>
15#include <private/qwaylandview_p.h>
16#include <QWaylandQuickOutput>
17#include <QQuickWindow>
19#include <qpa/qlatformscreen_p.h>
21using namespace QNativeInterface::
Private;
25Vsp2Buffer::Vsp2Buffer(wl_kms_buffer *kmsBuffer)
26 : dmabufFd(kmsBuffer->fd)
27 , bytesPerLine(kmsBuffer->stride)
28 , drmPixelFormat(kmsBuffer->format)
29 , size(kmsBuffer->width, kmsBuffer->height)
36 auto *wlItem = m_hwLayer->waylandItem();
37 m_screen =
dynamic_cast<QVsp2Screen*>(wlItem->window()->screen()->handle());
40 connect(hwLayer, &QWaylandQuickHardwareLayer::stackingLevelChanged,
this, [integration](){
41 integration->recreateVspLayers();
46 hwLayer->setSceneGraphPainting(
false);
47 QWaylandViewPrivate::get(hwLayer->waylandItem()->view())->independentFrameCallback =
true;
53 auto *kmsBuffer = nextKmsBuffer();
58 m_buffer = Vsp2Buffer(kmsBuffer);
61 m_layerIndex = m_screen->addLayer(m_buffer.dmabufFd, m_buffer.size, m_position, m_buffer.drmPixelFormat, m_buffer.bytesPerLine);
63 auto *wlItem = m_hwLayer->waylandItem();
64 wlItem->surface()->frameStarted();
70 m_screen->removeLayer(m_layerIndex);
82 auto *kmsBuffer = nextKmsBuffer();
85 if (m_buffer.dmabufFd != -1) {
86 bool formatChanged =
false;
87 formatChanged |= newBuffer.bytesPerLine != m_buffer.bytesPerLine;
88 formatChanged |= newBuffer.size != m_buffer.size;
89 formatChanged |= newBuffer.drmPixelFormat != m_buffer.drmPixelFormat;
91 qWarning() <<
"The VSP2 Wayland hardware layer integration doesn't support changing"
92 <<
"surface formats, this will most likely fail";
97 m_screen->setLayerBuffer(m_layerIndex, m_buffer.dmabufFd);
99 auto *wlItem = m_hwLayer->waylandItem();
100 wlItem->surface()->frameStarted();
105 auto newSurface = m_hwLayer->waylandItem()->surface();
107 if (Q_UNLIKELY(newSurface == m_surface))
111 disconnect(
this->m_surface, &QWaylandSurface::redraw,
this, &Vsp2Layer::handleBufferCommitted);
113 connect(newSurface, &QWaylandSurface::redraw,
this, &Vsp2Layer::handleBufferCommitted, Qt::DirectConnection);
115 this->m_surface = newSurface;
120 QWaylandQuickItem *wlItem = m_hwLayer->waylandItem();
121 QRectF localGeometry(0, 0, wlItem->width(), wlItem->height());
122 auto lastMatrix = QWaylandQuickItemPrivate::get(wlItem)->lastMatrix;
123 auto globalGeometry = lastMatrix.mapRect(localGeometry);
125 if (m_buffer.size != globalGeometry.size().toSize()) {
126 qWarning() <<
"wl_buffer size != WaylandQuickItem size and scaling has not been"
127 <<
"implemented for the vsp2 hardware layer integration";
130 m_position = globalGeometry.topLeft().toPoint();
132 m_screen->setLayerPosition(m_layerIndex, m_position);
138 qreal opacity = m_hwLayer->waylandItem()->opacity();
139 m_screen->setLayerAlpha(m_layerIndex, opacity);
145 Q_ASSERT(m_hwLayer && m_hwLayer->waylandItem());
146 QWaylandQuickItem *wlItem = m_hwLayer->waylandItem();
147 auto view = wlItem->view();
151 auto wlBuffer = view->currentBuffer().wl_buffer();
156 struct wl_kms_buffer *kmsBuffer = wayland_kms_buffer_get(wlBuffer);
159 qWarning() <<
"Failed to get wl_kms_buffer for wl_buffer:" << wl_resource_get_id(wlBuffer);
166 for (
auto &layer : std::as_const(m_layers)) {
167 Q_ASSERT(!layer->isEnabled());
168 layer->enableVspLayer();
174 for (
auto it = m_layers.rbegin(); it != m_layers.rend(); ++it) {
175 if ((*it)->isEnabled())
176 (*it)->disableVspLayer();
182 std::sort(m_layers.begin(), m_layers.end(), [](
auto &l1,
auto &l2){
183 return l1->hwLayer()->stackingLevel() < l2->hwLayer()->stackingLevel();
195 if (QGuiApplication::platformName() !=
"eglfs") {
196 qWarning() <<
"Vsp2 layers are currently only supported on the eglfs platform plugin"
197 <<
"with the eglfs_kms_vsp2 device integration.\n"
198 <<
"You need to set QT_QPA_PLATFORM=eglfs and QT_QPA_EGLFS_INTEGRATION=eglfs_kms_vsp2";
201 auto screen =
dynamic_cast<QVsp2Screen*>(QGuiApplication::primaryScreen()->handle());
202 screen->addBlendListener([](){
210 m_layers.append(QSharedPointer<Vsp2Layer>(
new Vsp2Layer(hwLayer,
this)));
218 for (
auto it = m_layers.begin(); it != m_layers.end(); ++it) {
219 if ((*it)->hwLayer() == hwLayer) {
229 for (
auto &layer : std::as_const(m_layers)) {
230 if (
auto *surface = layer->hwLayer()->waylandItem()->surface())
231 surface->sendFrameCallbacks();
void sendFrameCallbacks()
void add(QWaylandQuickHardwareLayer *layer) override
void remove(QWaylandQuickHardwareLayer *layer) override
void handleSurfaceChanged()
Vsp2Buffer(wl_kms_buffer *kmsBuffer)