backends/drm: implement damage tracking for multi gpu transfers

Doesn't seem to help on my system, but maybe it helps with different drivers
This commit is contained in:
Xaver Hugl 2024-08-19 18:58:14 +02:00
parent 36c447a35a
commit 8a5f469f95
3 changed files with 23 additions and 15 deletions

View file

@ -57,7 +57,7 @@ std::optional<OutputLayerBeginFrameInfo> 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)

View file

@ -74,7 +74,7 @@ void EglGbmLayerSurface::destroyResources()
m_oldSurface = {};
}
std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash<uint32_t, QList<uint64_t>> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr<IccProfile> &iccProfile)
std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash<uint32_t, QList<uint64_t>> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr<IccProfile> &iccProfile, double scale)
{
if (!checkSurface(bufferSize, formats)) {
return std::nullopt;
@ -94,6 +94,7 @@ std::optional<OutputLayerBeginFrameInfo> 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<DrmFramebuffer> 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<DrmFramebuffer> EglGbmLayerSurface::doRenderTestBuffer(Surface *
}
}
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importBuffer(Surface *surface, EglSwapchainSlot *slot, FileDescriptor &&readFence, OutputFrame *frame) const
std::shared_ptr<DrmFramebuffer> 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<DrmFramebuffer> EglGbmLayerSurface::importBuffer(Surface *surfac
}
}
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame) const
std::shared_ptr<DrmFramebuffer> 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<DrmFramebuffer> 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<DrmFramebuffer> 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);

View file

@ -56,7 +56,7 @@ public:
EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, BufferTarget target = BufferTarget::Normal, FormatOption formatOption = FormatOption::PreferAlpha);
~EglGbmLayerSurface();
std::optional<OutputLayerBeginFrameInfo> startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash<uint32_t, QList<uint64_t>> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr<IccProfile> &iccProfile);
std::optional<OutputLayerBeginFrameInfo> startRendering(const QSize &bufferSize, OutputTransform transformation, const QHash<uint32_t, QList<uint64_t>> &formats, const ColorDescription &colorDescription, const QVector3D &channelFactors, const std::shared_ptr<IccProfile> &iccProfile, double scale);
bool endRendering(const QRegion &damagedRegion, OutputFrame *frame);
bool doesSurfaceFit(const QSize &size, const QHash<uint32_t, QList<uint64_t>> &formats) const;
@ -91,8 +91,10 @@ private:
QHash<GraphicsBuffer *, std::shared_ptr<GLTexture>> importedTextureCache;
QImage cpuCopyCache;
MultiGpuImportMode importMode;
DamageJournal importDamageJournal;
std::shared_ptr<DrmFramebuffer> currentFramebuffer;
BufferTarget bufferTarget;
double scale = 1;
// for color management
bool needsShadowBuffer = false;
@ -114,8 +116,8 @@ private:
std::shared_ptr<EglSwapchain> createGbmSwapchain(DrmGpu *gpu, EglContext *context, const QSize &size, uint32_t format, const QList<uint64_t> &modifiers, MultiGpuImportMode importMode, BufferTarget bufferTarget) const;
std::shared_ptr<DrmFramebuffer> doRenderTestBuffer(Surface *surface) const;
std::shared_ptr<DrmFramebuffer> importBuffer(Surface *surface, EglSwapchainSlot *source, FileDescriptor &&readFence, OutputFrame *frame) const;
std::shared_ptr<DrmFramebuffer> importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame) const;
std::shared_ptr<DrmFramebuffer> importBuffer(Surface *surface, EglSwapchainSlot *source, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const;
std::shared_ptr<DrmFramebuffer> importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer, FileDescriptor &&readFence, OutputFrame *frame, const QRegion &damagedRegion) const;
std::shared_ptr<DrmFramebuffer> importWithCpu(Surface *surface, EglSwapchainSlot *source, OutputFrame *frame) const;
std::unique_ptr<Surface> m_surface;