platforms/drm: multi-gpu buffer import with modifiers

This commit is contained in:
Xaver Hugl 2021-08-25 00:45:43 +02:00
parent 35ec9b87a7
commit e6cab81b53
3 changed files with 53 additions and 23 deletions

View file

@ -41,11 +41,15 @@ public:
Q_UNUSED(stride) Q_UNUSED(stride)
return false; return false;
} }
virtual int exportFramebufferAsDmabuf(DrmAbstractOutput *output, uint32_t *format, uint32_t *stride) { virtual bool exportFramebufferAsDmabuf(DrmAbstractOutput *output, int *fds, int *strides, int *offsets, uint32_t *num_fds, uint32_t *format, uint64_t *modifier) {
Q_UNUSED(output) Q_UNUSED(output)
Q_UNUSED(fds)
Q_UNUSED(strides)
Q_UNUSED(offsets)
Q_UNUSED(num_fds)
Q_UNUSED(format) Q_UNUSED(format)
Q_UNUSED(stride) Q_UNUSED(modifier)
return 0; return false;
} }
virtual QRegion beginFrameForSecondaryGpu(DrmAbstractOutput *output) { virtual QRegion beginFrameForSecondaryGpu(DrmAbstractOutput *output) {
Q_UNUSED(output) Q_UNUSED(output)

View file

@ -270,7 +270,7 @@ bool EglGbmBackend::exportFramebuffer(DrmAbstractOutput *drmOutput, void *data,
return memcpy(data, bo->mappedData(), size.height() * stride); return memcpy(data, bo->mappedData(), size.height() * stride);
} }
int EglGbmBackend::exportFramebufferAsDmabuf(DrmAbstractOutput *drmOutput, uint32_t *format, uint32_t *stride) bool EglGbmBackend::exportFramebufferAsDmabuf(DrmAbstractOutput *drmOutput, int *fds, int *strides, int *offsets, uint32_t *num_fds, uint32_t *format, uint64_t *modifier)
{ {
auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(), auto it = std::find_if(m_secondaryGpuOutputs.begin(), m_secondaryGpuOutputs.end(),
[drmOutput] (const Output &output) { [drmOutput] (const Output &output) {
@ -281,14 +281,33 @@ int EglGbmBackend::exportFramebufferAsDmabuf(DrmAbstractOutput *drmOutput, uint3
return -1; return -1;
} }
auto bo = it->current.gbmSurface->currentBuffer()->getBo(); auto bo = it->current.gbmSurface->currentBuffer()->getBo();
int fd = gbm_bo_get_fd(bo); if (gbm_bo_get_handle_for_plane(bo, 0).s32 != -1) {
if (fd == -1) { *num_fds = gbm_bo_get_plane_count(bo);
qCWarning(KWIN_DRM) << "failed to export gbm_bo as dma-buf:" << strerror(errno); for (uint32_t i = 0; i < *num_fds; i++) {
return -1; fds[i] = gbm_bo_get_fd_for_plane(bo, i);
if (fds[i] < 0) {
qCWarning(KWIN_DRM) << "failed to export gbm_bo as dma-buf:" << strerror(errno);
for (uint32_t f = 0; f < i; f++) {
close(fds[f]);
}
return false;
}
strides[i] = gbm_bo_get_stride_for_plane(bo, i);
offsets[i] = gbm_bo_get_offset(bo, i);
}
*modifier = gbm_bo_get_modifier(bo);
} else {
fds[0] = gbm_bo_get_fd(bo);
if (fds[0] < 0) {
qCWarning(KWIN_DRM) << "failed to export gbm_bo as dma-buf:" << strerror(errno);
return false;
}
*num_fds = 1;
strides[0] = gbm_bo_get_stride(bo);
*modifier = DRM_FORMAT_MOD_INVALID;
} }
*format = gbm_bo_get_format(bo); *format = gbm_bo_get_format(bo);
*stride = gbm_bo_get_stride(bo); return true;
return fd;
} }
QRegion EglGbmBackend::beginFrameForSecondaryGpu(DrmAbstractOutput *drmOutput) QRegion EglGbmBackend::beginFrameForSecondaryGpu(DrmAbstractOutput *drmOutput)
@ -312,18 +331,25 @@ QSharedPointer<DrmBuffer> EglGbmBackend::importFramebuffer(Output &output, const
} }
const auto size = output.output->modeSize(); const auto size = output.output->modeSize();
if (output.current.importMode == ImportMode::Dmabuf) { if (output.current.importMode == ImportMode::Dmabuf) {
uint32_t stride = 0; struct gbm_import_fd_modifier_data data;
uint32_t format = 0; data.width = size.width();
int fd = renderingBackend()->exportFramebufferAsDmabuf(output.output, &format, &stride); data.height = size.height();
if (fd != -1) { if (renderingBackend()->exportFramebufferAsDmabuf(output.output, data.fds, data.strides, data.offsets, &data.num_fds, &data.format, &data.modifier)) {
struct gbm_import_fd_data data = {}; gbm_bo *importedBuffer = nullptr;
data.fd = fd; if (data.modifier == DRM_FORMAT_MOD_INVALID) {
data.width = (uint32_t) size.width(); struct gbm_import_fd_data data1;
data.height = (uint32_t) size.height(); data1.fd = data.fds[0];
data.stride = stride; data1.width = size.width();
data.format = format; data1.height = size.height();
gbm_bo *importedBuffer = gbm_bo_import(m_gpu->gbmDevice(), GBM_BO_IMPORT_FD, &data, GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR); data1.stride = data.strides[0];
close(fd); data1.format = data.format;
importedBuffer = gbm_bo_import(m_gpu->gbmDevice(), GBM_BO_IMPORT_FD, &data1, GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR);
} else {
importedBuffer = gbm_bo_import(m_gpu->gbmDevice(), GBM_BO_IMPORT_FD_MODIFIER, &data, 0);
}
for (uint32_t i = 0; i < data.num_fds; i++) {
close(data.fds[i]);
}
if (importedBuffer) { if (importedBuffer) {
auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, importedBuffer, nullptr); auto buffer = QSharedPointer<DrmGbmBuffer>::create(m_gpu, importedBuffer, nullptr);
if (buffer->bufferId() > 0) { if (buffer->bufferId() > 0) {

View file

@ -62,7 +62,7 @@ public:
void removeOutput(DrmAbstractOutput *output) override; void removeOutput(DrmAbstractOutput *output) override;
bool swapBuffers(DrmAbstractOutput *output, const QRegion &dirty) override; bool swapBuffers(DrmAbstractOutput *output, const QRegion &dirty) override;
bool exportFramebuffer(DrmAbstractOutput *output, void *data, const QSize &size, uint32_t stride) override; bool exportFramebuffer(DrmAbstractOutput *output, void *data, const QSize &size, uint32_t stride) override;
int exportFramebufferAsDmabuf(DrmAbstractOutput *output, uint32_t *format, uint32_t *stride) override; bool exportFramebufferAsDmabuf(DrmAbstractOutput *output, int *fds, int *strides, int *offsets, uint32_t *num_fds, uint32_t *format, uint64_t *modifier) override;
QRegion beginFrameForSecondaryGpu(DrmAbstractOutput *output) override; QRegion beginFrameForSecondaryGpu(DrmAbstractOutput *output) override;
bool directScanoutAllowed(int screen) const override; bool directScanoutAllowed(int screen) const override;