9#include <qeglfskmshelpers_p.h>
11#include <QtCore/QLoggingCategory>
12#include <QtGui/private/qguiapplication_p.h>
14#include <drm_fourcc.h>
21#include <mediactl/mediactl.h>
22#include <mediactl/v4l2subdev.h>
31 Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
37 Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
44 auto dmabuf =
static_cast<DmaBuffer *>(data);
51 auto existingBuffer =
static_cast<DmaBuffer *>(gbm_bo_get_user_data(gbmBo));
53 return existingBuffer;
55 uint32_t handle = gbm_bo_get_handle(gbmBo).u32;
56 QScopedPointer<DmaBuffer> fb(
new DmaBuffer);
57 int ret = drmPrimeHandleToFD(device()->fd(), handle, DRM_CLOEXEC, &fb->dmabufFd);
59 qWarning(
"Failed to create dmabuf file descriptor for buffer with drmPrimeHandleToFd");
63 gbm_bo_set_user_data(gbmBo, fb.data(), dmaBufferDestroyedHandler);
76 uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format);
77 qCDebug(qLcEglfsKmsDebug,
"Creating gbm_surface for screen %s with format 0x%x", qPrintable(name()), gbmFormat);
78 Q_ASSERT(rawGeometry().isValid());
80 uint(rawGeometry().width()),
81 uint(rawGeometry().height()),
83 GBM_BO_USE_RENDERING);
89 if (m_frameBuffers[m_backFb].dmabufFd == -1)
97 m_gbmSurface =
nullptr;
102 for (
auto &fb : m_frameBuffers)
103 initDumbFrameBuffer(fb);
108 qCDebug(qLcEglfsKmsDebug,
"Initializing Vsp2 hardware");
109 m_blendDevice.reset(
new QVsp2BlendingDevice(rawGeometry().size()));
117 const QSize screenSize = rawGeometry().size();
118 const uint bytesPerLine = uint(screenSize.width()) * 4;
119 bool formatSet = m_blendDevice->enableInput(m_qtLayer, QRect(QPoint(), screenSize), m_output.drm_format, bytesPerLine);
121 const uint32_t fallbackFormat = DRM_FORMAT_ARGB8888;
122 qWarning() <<
"Failed to set format" << q_fourccToString(m_output.drm_format)
123 <<
"falling back to" << q_fourccToString(fallbackFormat);
124 formatSet = m_blendDevice->enableInput(m_qtLayer, QRect(QPoint(), screenSize), fallbackFormat, bytesPerLine);
126 qFatal(
"Failed to set vsp2 blending format");
132 int index = m_blendDevice->enableInput(QRect(position, size), drmPixelFormat, bytesPerLine);
134 m_blendDevice->setInputBuffer(index, dmabufFd);
136 qCDebug(qLcEglfsKmsDebug) <<
"Enabled extra layer for vsp input" << index;
139 qWarning() <<
"Failed to add layer";
146 m_blendDevice->setInputBuffer(layerIndex, dmabufFd);
147 if (!m_blendScheduled) {
148 m_blendScheduled =
true;
149 QCoreApplication::postEvent(m_blender.data(),
new QEvent(QEvent::User));
156 m_blendDevice->setInputPosition(layerIndex, position);
162 m_blendDevice->setInputAlpha(layerIndex, alpha);
168 m_blendDevice->disableInput(layerIndex);
174 m_blendFinishedCallbacks.append(callback);
180 qWarning(
"Cannot sync before platform init!");
184 if (!m_blendScheduled && !m_nextGbmBo) {
185 m_nextGbmBo = gbm_surface_lock_front_buffer(m_gbmSurface);
188 qWarning(
"Could not lock GBM surface front buffer!");
192 m_blendScheduled =
true;
193 QCoreApplication::postEvent(m_blender.data(),
new QEvent(QEvent::User));
199 const int driFd = device()->fd();
200 QKmsOutput &op(output());
202 int ret = drmModeSetCrtc(driFd,
204 m_frameBuffers[m_backFb].drmBufferId,
210 qErrnoWarning(errno,
"Could not set DRM mode!");
213 setPowerState(PowerStateOn);
220 QKmsOutput &op(output());
221 const int driFd = device()->fd();
223 int ret = drmModePageFlip(driFd,
225 m_frameBuffers[m_backFb].drmBufferId,
230 qErrnoWarning(
"Could not queue DRM page flip on screen %s", qPrintable(name()));
232 m_backFb = (m_backFb + 1) % 2;
237 m_blendScheduled =
false;
238 if (!m_nextGbmBo && !m_blendDevice->isDirty())
241 FrameBuffer &backBuffer = m_frameBuffers[m_backFb];
242 if (backBuffer.dmabufFd == -1)
246 Q_ASSERT(m_nextGbmBo != m_currentGbmBo);
247 int compositorBackBufferDmaFd = dmaBufferForGbmBuffer(m_nextGbmBo)->dmabufFd;
248 m_blendDevice->setInputBuffer(m_qtLayer, compositorBackBufferDmaFd);
251 gbm_surface_release_buffer(m_gbmSurface, m_currentGbmBo);
252 m_currentGbmBo = m_nextGbmBo;
253 m_nextGbmBo =
nullptr;
261 if (!m_blendDevice->isDirty())
264 const int driFd = device()->fd();
266 vBlank.request.type =
static_cast<drmVBlankSeqType>(DRM_VBLANK_RELATIVE | DRM_VBLANK_SECONDARY);
267 vBlank.request.sequence = 1;
268 vBlank.request.signal = 0;
269 drmWaitVBlank(driFd, &vBlank);
271 if (!m_blendDevice->blend(backBuffer.dmabufFd)) {
272 qWarning() <<
"Vsp2: Blending failed";
275 m_blendDevice->disableInput(m_qtLayer);
279 for (
auto cb : m_blendFinishedCallbacks)
287 QKmsOutput &op(output());
288 const uint32_t width = op.modes[op.mode].hdisplay;
289 const uint32_t height = op.modes[op.mode].vdisplay;
291 Q_ASSERT(fb.dmabufFd == -1);
292 const uint32_t dumbBufferFlags = 0;
293 const uint32_t bpp = 32;
295 drm_mode_create_dumb creq = {
303 const int driFd = device()->fd();
304 if (drmIoctl(driFd, DRM_IOCTL_MODE_CREATE_DUMB, &creq) == -1)
305 qFatal(
"Failed to create dumb buffer: %s", strerror(errno));
313 uint32_t gbmBoHandles[4] = { creq.handle, 0, 0, 0 };
314 uint32_t strides[4] = { creq.pitch, 0, 0, 0 };
315 uint32_t offsets[4] = { 0 };
316 uint32_t pixelFormat = DRM_FORMAT_ARGB8888;
317 uint32_t drmFlags = 0;
319 qCDebug(qLcEglfsKmsDebug) <<
"Adding FB" << QSize(width, height)
320 <<
", DRM format" << q_fourccToString(pixelFormat);
321 int ret = drmModeAddFB2(driFd, width, height, pixelFormat,
322 gbmBoHandles, strides, offsets, &fb.drmBufferId, drmFlags);
324 qFatal(
"drmModeAddFB2 failed: %s", strerror(errno));
326 drmPrimeHandleToFD(driFd, gbmBoHandles[0], DRM_CLOEXEC, &fb.dmabufFd);
331 switch (event->type()) {
336 return QObject::event(event);
gbm_device * gbmDevice() const
bool removeLayer(int id) override
void setLayerPosition(int id, const QPoint &position) override
gbm_surface * createSurface()
void setLayerBuffer(int id, int dmabufFd) override
void addBlendListener(void(*callback)()) override
int addLayer(int dmabufFd, const QSize &size, const QPoint &position, uint drmPixelFormat, uint bytesPerLine) override
void setLayerAlpha(int id, qreal alpha) override
void initDumbFrameBuffers()
QEglFSKmsVsp2Screen(QEglFSKmsDevice *device, const QKmsOutput &output)
static QT_BEGIN_NAMESPACE uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
static uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)