From 8a5f469f95f5171e482fcd06653d275ad1edf832 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Mon, 19 Aug 2024 18:58:14 +0200 Subject: [PATCH] backends/drm: implement damage tracking for multi gpu transfers Doesn't seem to help on my system, but maybe it helps with different drivers --- src/backends/drm/drm_egl_layer.cpp | 2 +- src/backends/drm/drm_egl_layer_surface.cpp | 28 +++++++++++++--------- src/backends/drm/drm_egl_layer_surface.h | 8 ++++--- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/backends/drm/drm_egl_layer.cpp b/src/backends/drm/drm_egl_layer.cpp index ae9cfe2ddf..7b7c19c215 100644 --- a/src/backends/drm/drm_egl_layer.cpp +++ b/src/backends/drm/drm_egl_layer.cpp @@ -57,7 +57,7 @@ std::optional EglGbmLayer::doBeginFrame() m_scanoutBuffer.reset(); m_colorPipeline = ColorPipeline{}; return m_surface.startRendering(targetRect().size(), m_pipeline->output()->transform().combine(OutputTransform::FlipY), m_pipeline->formats(m_type), m_pipeline->output()->scanoutColorDescription(), - m_pipeline->output()->needsChannelFactorFallback() ? m_pipeline->output()->effectiveChannelFactors() : QVector3D(1, 1, 1), m_pipeline->iccProfile()); + m_pipeline->output()->needsChannelFactorFallback() ? m_pipeline->output()->effectiveChannelFactors() : QVector3D(1, 1, 1), m_pipeline->iccProfile(), m_pipeline->output()->scale()); } bool EglGbmLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion, OutputFrame *frame) diff --git a/src/backends/drm/drm_egl_layer_surface.cpp b/src/backends/drm/drm_egl_layer_surface.cpp index 0598731a14..e201c98e49 100644 --- a/src/backends/drm/drm_egl_layer_surface.cpp +++ b/src/backends/drm/drm_egl_layer_surface.cpp @@ -74,7 +74,7 @@ void EglGbmLayerSurface::destroyResources() m_oldSurface = {}; } -std::optional EglGbmLayerSurface::startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr &iccProfile) +std::optional EglGbmLayerSurface::startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr &iccProfile, double scale) { if (!checkSurface(bufferSize, formats)) { return std::nullopt; @@ -94,6 +94,7 @@ std::optional EglGbmLayerSurface::startRendering(cons } slot->framebuffer()->colorAttachment()->setContentTransform(transformation); m_surface->currentSlot = slot; + m_surface->scale = scale; if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->iccProfile != iccProfile) { m_surface->damageJournal.clear(); @@ -225,7 +226,7 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame glFinish(); } m_surface->gbmSwapchain->release(m_surface->currentSlot, sourceFence.fileDescriptor().duplicate()); - const auto buffer = importBuffer(m_surface.get(), m_surface->currentSlot.get(), sourceFence.takeFileDescriptor(), frame); + const auto buffer = importBuffer(m_surface.get(), m_surface->currentSlot.get(), sourceFence.takeFileDescriptor(), frame, damagedRegion); if (buffer) { m_surface->currentFramebuffer = buffer; return true; @@ -517,7 +518,7 @@ std::shared_ptr EglGbmLayerSurface::doRenderTestBuffer(Surface * if (!slot) { return nullptr; } - if (const auto ret = importBuffer(surface, slot.get(), FileDescriptor{}, nullptr)) { + if (const auto ret = importBuffer(surface, slot.get(), FileDescriptor{}, nullptr, infiniteRegion())) { surface->currentSlot = slot; surface->currentFramebuffer = ret; return ret; @@ -526,12 +527,12 @@ std::shared_ptr EglGbmLayerSurface::doRenderTestBuffer(Surface * } } -std::shared_ptr EglGbmLayerSurface::importBuffer(Surface *surface, EglSwapchainSlot *slot, FileDescriptor &&readFence, OutputFrame *frame) const +std::shared_ptr EglGbmLayerSurface::importBuffer(Surface *surface, EglSwapchainSlot *slot, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const { if (surface->bufferTarget == BufferTarget::Dumb || surface->importMode == MultiGpuImportMode::DumbBuffer) { return importWithCpu(surface, slot, frame); } else if (surface->importMode == MultiGpuImportMode::Egl) { - return importWithEgl(surface, slot->buffer(), std::move(readFence), frame); + return importWithEgl(surface, slot->buffer(), std::move(readFence), frame, damagedRegion); } else { const auto ret = m_gpu->importBuffer(slot->buffer(), std::move(readFence)); if (!ret) { @@ -541,7 +542,7 @@ std::shared_ptr EglGbmLayerSurface::importBuffer(Surface *surfac } } -std::shared_ptr EglGbmLayerSurface::importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame) const +std::shared_ptr EglGbmLayerSurface::importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const { Q_ASSERT(surface->importGbmSwapchain); @@ -579,9 +580,15 @@ std::shared_ptr EglGbmLayerSurface::importWithEgl(Surface *surfa return nullptr; } + QRegion deviceDamage; + for (const QRect &logical : damagedRegion) { + deviceDamage |= scaledRect(logical, surface->scale).toAlignedRect(); + } + const QRegion repaint = deviceDamage | surface->importDamageJournal.accumulate(slot->age(), infiniteRegion()); + surface->importDamageJournal.add(deviceDamage); + GLFramebuffer *fbo = slot->framebuffer(); - glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle()); - glViewport(0, 0, fbo->size().width(), fbo->size().height()); + surface->importContext->pushFramebuffer(fbo); const auto shader = surface->importContext->shaderManager()->pushShader(sourceTexture->target() == GL_TEXTURE_EXTERNAL_OES ? ShaderTrait::MapExternalTexture : ShaderTrait::MapTexture); QMatrix4x4 mat; @@ -590,11 +597,10 @@ std::shared_ptr EglGbmLayerSurface::importWithEgl(Surface *surfa shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat); sourceTexture->bind(); - sourceTexture->render(fbo->size()); + sourceTexture->render(repaint, fbo->size(), true); sourceTexture->unbind(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - + surface->importContext->popFramebuffer(); surface->importContext->shaderManager()->popShader(); glFlush(); EGLNativeFence endFence(display); diff --git a/src/backends/drm/drm_egl_layer_surface.h b/src/backends/drm/drm_egl_layer_surface.h index f501c8c162..75da57b15b 100644 --- a/src/backends/drm/drm_egl_layer_surface.h +++ b/src/backends/drm/drm_egl_layer_surface.h @@ -56,7 +56,7 @@ public: EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, BufferTarget target = BufferTarget::Normal, FormatOption formatOption = FormatOption::PreferAlpha); ~EglGbmLayerSurface(); - std::optional startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr &iccProfile); + std::optional startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr &iccProfile, double scale); bool endRendering(const QRegion &damagedRegion, OutputFrame *frame); bool doesSurfaceFit(const QSize &size, const QHash> &formats) const; @@ -91,8 +91,10 @@ private: QHash> importedTextureCache; QImage cpuCopyCache; MultiGpuImportMode importMode; + DamageJournal importDamageJournal; std::shared_ptr currentFramebuffer; BufferTarget bufferTarget; + double scale = 1; // for color management bool needsShadowBuffer = false; @@ -114,8 +116,8 @@ private: std::shared_ptr createGbmSwapchain(DrmGpu *gpu, EglContext *context, const QSize &size, uint32_t format, const QList &modifiers, MultiGpuImportMode importMode, BufferTarget bufferTarget) const; std::shared_ptr doRenderTestBuffer(Surface *surface) const; - std::shared_ptr importBuffer(Surface *surface, EglSwapchainSlot *source, FileDescriptor &&readFence, OutputFrame *frame) const; - std::shared_ptr importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame) const; + std::shared_ptr importBuffer(Surface *surface, EglSwapchainSlot *source, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const; + std::shared_ptr importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const; std::shared_ptr importWithCpu(Surface *surface, EglSwapchainSlot *source, OutputFrame *frame) const; std::unique_ptr m_surface;