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:
parent
36c447a35a
commit
8a5f469f95
3 changed files with 23 additions and 15 deletions
|
@ -57,7 +57,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::doBeginFrame()
|
||||||
m_scanoutBuffer.reset();
|
m_scanoutBuffer.reset();
|
||||||
m_colorPipeline = ColorPipeline{};
|
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(),
|
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)
|
bool EglGbmLayer::doEndFrame(const QRegion &renderedRegion, const QRegion &damagedRegion, OutputFrame *frame)
|
||||||
|
|
|
@ -74,7 +74,7 @@ void EglGbmLayerSurface::destroyResources()
|
||||||
m_oldSurface = {};
|
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)) {
|
if (!checkSurface(bufferSize, formats)) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -94,6 +94,7 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
|
||||||
}
|
}
|
||||||
slot->framebuffer()->colorAttachment()->setContentTransform(transformation);
|
slot->framebuffer()->colorAttachment()->setContentTransform(transformation);
|
||||||
m_surface->currentSlot = slot;
|
m_surface->currentSlot = slot;
|
||||||
|
m_surface->scale = scale;
|
||||||
|
|
||||||
if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->iccProfile != iccProfile) {
|
if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->iccProfile != iccProfile) {
|
||||||
m_surface->damageJournal.clear();
|
m_surface->damageJournal.clear();
|
||||||
|
@ -225,7 +226,7 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion, OutputFrame
|
||||||
glFinish();
|
glFinish();
|
||||||
}
|
}
|
||||||
m_surface->gbmSwapchain->release(m_surface->currentSlot, sourceFence.fileDescriptor().duplicate());
|
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) {
|
if (buffer) {
|
||||||
m_surface->currentFramebuffer = buffer;
|
m_surface->currentFramebuffer = buffer;
|
||||||
return true;
|
return true;
|
||||||
|
@ -517,7 +518,7 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::doRenderTestBuffer(Surface *
|
||||||
if (!slot) {
|
if (!slot) {
|
||||||
return nullptr;
|
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->currentSlot = slot;
|
||||||
surface->currentFramebuffer = ret;
|
surface->currentFramebuffer = ret;
|
||||||
return 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) {
|
if (surface->bufferTarget == BufferTarget::Dumb || surface->importMode == MultiGpuImportMode::DumbBuffer) {
|
||||||
return importWithCpu(surface, slot, frame);
|
return importWithCpu(surface, slot, frame);
|
||||||
} else if (surface->importMode == MultiGpuImportMode::Egl) {
|
} 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 {
|
} else {
|
||||||
const auto ret = m_gpu->importBuffer(slot->buffer(), std::move(readFence));
|
const auto ret = m_gpu->importBuffer(slot->buffer(), std::move(readFence));
|
||||||
if (!ret) {
|
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);
|
Q_ASSERT(surface->importGbmSwapchain);
|
||||||
|
|
||||||
|
@ -579,9 +580,15 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface *surfa
|
||||||
return nullptr;
|
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();
|
GLFramebuffer *fbo = slot->framebuffer();
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle());
|
surface->importContext->pushFramebuffer(fbo);
|
||||||
glViewport(0, 0, fbo->size().width(), fbo->size().height());
|
|
||||||
|
|
||||||
const auto shader = surface->importContext->shaderManager()->pushShader(sourceTexture->target() == GL_TEXTURE_EXTERNAL_OES ? ShaderTrait::MapExternalTexture : ShaderTrait::MapTexture);
|
const auto shader = surface->importContext->shaderManager()->pushShader(sourceTexture->target() == GL_TEXTURE_EXTERNAL_OES ? ShaderTrait::MapExternalTexture : ShaderTrait::MapTexture);
|
||||||
QMatrix4x4 mat;
|
QMatrix4x4 mat;
|
||||||
|
@ -590,11 +597,10 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface *surfa
|
||||||
shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat);
|
shader->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, mat);
|
||||||
|
|
||||||
sourceTexture->bind();
|
sourceTexture->bind();
|
||||||
sourceTexture->render(fbo->size());
|
sourceTexture->render(repaint, fbo->size(), true);
|
||||||
sourceTexture->unbind();
|
sourceTexture->unbind();
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
surface->importContext->popFramebuffer();
|
||||||
|
|
||||||
surface->importContext->shaderManager()->popShader();
|
surface->importContext->shaderManager()->popShader();
|
||||||
glFlush();
|
glFlush();
|
||||||
EGLNativeFence endFence(display);
|
EGLNativeFence endFence(display);
|
||||||
|
|
|
@ -56,7 +56,7 @@ public:
|
||||||
EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, BufferTarget target = BufferTarget::Normal, FormatOption formatOption = FormatOption::PreferAlpha);
|
EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, BufferTarget target = BufferTarget::Normal, FormatOption formatOption = FormatOption::PreferAlpha);
|
||||||
~EglGbmLayerSurface();
|
~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 endRendering(const QRegion &damagedRegion, OutputFrame *frame);
|
||||||
|
|
||||||
bool doesSurfaceFit(const QSize &size, const QHash<uint32_t, QList<uint64_t>> &formats) const;
|
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;
|
QHash<GraphicsBuffer *, std::shared_ptr<GLTexture>> importedTextureCache;
|
||||||
QImage cpuCopyCache;
|
QImage cpuCopyCache;
|
||||||
MultiGpuImportMode importMode;
|
MultiGpuImportMode importMode;
|
||||||
|
DamageJournal importDamageJournal;
|
||||||
std::shared_ptr<DrmFramebuffer> currentFramebuffer;
|
std::shared_ptr<DrmFramebuffer> currentFramebuffer;
|
||||||
BufferTarget bufferTarget;
|
BufferTarget bufferTarget;
|
||||||
|
double scale = 1;
|
||||||
|
|
||||||
// for color management
|
// for color management
|
||||||
bool needsShadowBuffer = false;
|
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<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> doRenderTestBuffer(Surface *surface) const;
|
||||||
std::shared_ptr<DrmFramebuffer> importBuffer(Surface *surface, EglSwapchainSlot *source, 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;
|
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::shared_ptr<DrmFramebuffer> importWithCpu(Surface *surface, EglSwapchainSlot *source, OutputFrame *frame) const;
|
||||||
|
|
||||||
std::unique_ptr<Surface> m_surface;
|
std::unique_ptr<Surface> m_surface;
|
||||||
|
|
Loading…
Reference in a new issue