backends/drm: fix surface destruction

With value semantics, the destructor can be called more often than actually
desired, so this commit ports the DrmEglLayerSurface to use unique pointers to
store surface data instead
This commit is contained in:
Xaver Hugl 2023-09-27 18:39:42 +02:00
parent b266b08145
commit 88ab958f4d
2 changed files with 137 additions and 137 deletions

View file

@ -48,10 +48,7 @@ EglGbmLayerSurface::EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend, B
{ {
} }
EglGbmLayerSurface::~EglGbmLayerSurface() EglGbmLayerSurface::~EglGbmLayerSurface() = default;
{
destroyResources();
}
EglGbmLayerSurface::Surface::~Surface() EglGbmLayerSurface::Surface::~Surface()
{ {
@ -82,50 +79,50 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
return std::nullopt; return std::nullopt;
} }
auto slot = m_surface.gbmSwapchain->acquire(); auto slot = m_surface->gbmSwapchain->acquire();
if (!slot) { if (!slot) {
return std::nullopt; return std::nullopt;
} }
slot->framebuffer()->colorAttachment()->setContentTransform(transformation); slot->framebuffer()->colorAttachment()->setContentTransform(transformation);
m_surface.currentSlot = slot; m_surface->currentSlot = slot;
if (m_surface.targetColorDescription != colorDescription || m_surface.channelFactors != channelFactors || m_surface.colormanagementEnabled != enableColormanagement) { if (m_surface->targetColorDescription != colorDescription || m_surface->channelFactors != channelFactors || m_surface->colormanagementEnabled != enableColormanagement) {
m_surface.damageJournal.clear(); m_surface->damageJournal.clear();
m_surface.colormanagementEnabled = enableColormanagement; m_surface->colormanagementEnabled = enableColormanagement;
m_surface.targetColorDescription = colorDescription; m_surface->targetColorDescription = colorDescription;
m_surface.channelFactors = channelFactors; m_surface->channelFactors = channelFactors;
if (enableColormanagement) { if (enableColormanagement) {
m_surface.intermediaryColorDescription = ColorDescription(colorDescription.colorimetry(), NamedTransferFunction::linear, m_surface->intermediaryColorDescription = ColorDescription(colorDescription.colorimetry(), NamedTransferFunction::linear,
colorDescription.sdrBrightness(), colorDescription.minHdrBrightness(), colorDescription.sdrBrightness(), colorDescription.minHdrBrightness(),
colorDescription.maxHdrBrightness(), colorDescription.maxHdrHighlightBrightness()); colorDescription.maxHdrBrightness(), colorDescription.maxHdrHighlightBrightness());
} else { } else {
m_surface.intermediaryColorDescription = colorDescription; m_surface->intermediaryColorDescription = colorDescription;
} }
} }
const QRegion repaint = bufferAgeEnabled ? m_surface.damageJournal.accumulate(slot->age(), infiniteRegion()) : infiniteRegion(); const QRegion repaint = bufferAgeEnabled ? m_surface->damageJournal.accumulate(slot->age(), infiniteRegion()) : infiniteRegion();
if (enableColormanagement) { if (enableColormanagement) {
if (!m_surface.shadowBuffer || m_surface.shadowTexture->size() != m_surface.gbmSwapchain->size()) { if (!m_surface->shadowBuffer || m_surface->shadowTexture->size() != m_surface->gbmSwapchain->size()) {
m_surface.shadowTexture = GLTexture::allocate(GL_RGBA16F, m_surface.gbmSwapchain->size()); m_surface->shadowTexture = GLTexture::allocate(GL_RGBA16F, m_surface->gbmSwapchain->size());
if (!m_surface.shadowTexture) { if (!m_surface->shadowTexture) {
return std::nullopt; return std::nullopt;
} }
m_surface.shadowBuffer = std::make_shared<GLFramebuffer>(m_surface.shadowTexture.get()); m_surface->shadowBuffer = std::make_unique<GLFramebuffer>(m_surface->shadowTexture.get());
} }
m_surface.renderStart = std::chrono::steady_clock::now(); m_surface->renderStart = std::chrono::steady_clock::now();
m_surface.timeQuery->begin(); m_surface->timeQuery->begin();
return OutputLayerBeginFrameInfo{ return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_surface.shadowBuffer.get(), m_surface.intermediaryColorDescription), .renderTarget = RenderTarget(m_surface->shadowBuffer.get(), m_surface->intermediaryColorDescription),
.repaint = repaint, .repaint = repaint,
}; };
} else { } else {
m_surface.shadowTexture.reset(); m_surface->shadowTexture.reset();
m_surface.shadowBuffer.reset(); m_surface->shadowBuffer.reset();
m_surface.renderStart = std::chrono::steady_clock::now(); m_surface->renderStart = std::chrono::steady_clock::now();
m_surface.timeQuery->begin(); m_surface->timeQuery->begin();
return OutputLayerBeginFrameInfo{ return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_surface.currentSlot->framebuffer()), .renderTarget = RenderTarget(m_surface->currentSlot->framebuffer()),
.repaint = repaint, .repaint = repaint,
}; };
} }
@ -133,8 +130,8 @@ std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(cons
bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion) bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion)
{ {
if (m_surface.colormanagementEnabled) { if (m_surface->colormanagementEnabled) {
GLFramebuffer *fbo = m_surface.currentSlot->framebuffer(); GLFramebuffer *fbo = m_surface->currentSlot->framebuffer();
GLTexture *texture = fbo->colorAttachment(); GLTexture *texture = fbo->colorAttachment();
GLFramebuffer::pushFramebuffer(fbo); GLFramebuffer::pushFramebuffer(fbo);
ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace); ShaderBinder binder(ShaderTrait::MapTexture | ShaderTrait::TransformColorspace);
@ -142,27 +139,27 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion)
mat.ortho(QRectF(QPointF(), fbo->size())); mat.ortho(QRectF(QPointF(), fbo->size()));
binder.shader()->setUniform(GLShader::MatrixUniform::ModelViewProjectionMatrix, mat); binder.shader()->setUniform(GLShader::MatrixUniform::ModelViewProjectionMatrix, mat);
QMatrix3x3 ctm; QMatrix3x3 ctm;
ctm(0, 0) = m_surface.channelFactors.x(); ctm(0, 0) = m_surface->channelFactors.x();
ctm(1, 1) = m_surface.channelFactors.y(); ctm(1, 1) = m_surface->channelFactors.y();
ctm(2, 2) = m_surface.channelFactors.z(); ctm(2, 2) = m_surface->channelFactors.z();
binder.shader()->setUniform(GLShader::MatrixUniform::ColorimetryTransformation, ctm); binder.shader()->setUniform(GLShader::MatrixUniform::ColorimetryTransformation, ctm);
binder.shader()->setUniform(GLShader::IntUniform::SourceNamedTransferFunction, int(m_surface.intermediaryColorDescription.transferFunction())); binder.shader()->setUniform(GLShader::IntUniform::SourceNamedTransferFunction, int(m_surface->intermediaryColorDescription.transferFunction()));
binder.shader()->setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, int(m_surface.targetColorDescription.transferFunction())); binder.shader()->setUniform(GLShader::IntUniform::DestinationNamedTransferFunction, int(m_surface->targetColorDescription.transferFunction()));
m_surface.shadowTexture->render(m_surface.gbmSwapchain->size(), 1); m_surface->shadowTexture->render(m_surface->gbmSwapchain->size(), 1);
GLFramebuffer::popFramebuffer(); GLFramebuffer::popFramebuffer();
} }
m_surface.damageJournal.add(damagedRegion); m_surface->damageJournal.add(damagedRegion);
m_surface.gbmSwapchain->release(m_surface.currentSlot); m_surface->gbmSwapchain->release(m_surface->currentSlot);
m_surface.timeQuery->end(); m_surface->timeQuery->end();
glFlush(); glFlush();
if (m_eglBackend->contextObject()->isSoftwareRenderer()) { if (m_eglBackend->contextObject()->isSoftwareRenderer()) {
// llvmpipe doesn't do synchronization properly: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9375 // llvmpipe doesn't do synchronization properly: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9375
glFinish(); glFinish();
} }
const auto buffer = importBuffer(m_surface, m_surface.currentSlot.get()); const auto buffer = importBuffer(m_surface.get(), m_surface->currentSlot.get());
m_surface.renderEnd = std::chrono::steady_clock::now(); m_surface->renderEnd = std::chrono::steady_clock::now();
if (buffer) { if (buffer) {
m_surface.currentFramebuffer = buffer; m_surface->currentFramebuffer = buffer;
return true; return true;
} else { } else {
return false; return false;
@ -171,12 +168,12 @@ bool EglGbmLayerSurface::endRendering(const QRegion &damagedRegion)
std::chrono::nanoseconds EglGbmLayerSurface::queryRenderTime() const std::chrono::nanoseconds EglGbmLayerSurface::queryRenderTime() const
{ {
const auto cpuTime = m_surface.renderEnd - m_surface.renderStart; const auto cpuTime = m_surface->renderEnd - m_surface->renderStart;
if (m_surface.timeQuery) { if (m_surface->timeQuery) {
m_eglBackend->makeCurrent(); m_eglBackend->makeCurrent();
auto gpuTime = m_surface.timeQuery->result(); auto gpuTime = m_surface->timeQuery->result();
if (m_surface.importTimeQuery && m_eglBackend->contextForGpu(m_gpu)->makeCurrent()) { if (m_surface->importTimeQuery && m_eglBackend->contextForGpu(m_gpu)->makeCurrent()) {
gpuTime += m_surface.importTimeQuery->result(); gpuTime += m_surface->importTimeQuery->result();
} }
return std::max(gpuTime, cpuTime); return std::max(gpuTime, cpuTime);
} else { } else {
@ -191,28 +188,28 @@ EglGbmBackend *EglGbmLayerSurface::eglBackend() const
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::currentBuffer() const std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::currentBuffer() const
{ {
return m_surface.currentFramebuffer; return m_surface->currentFramebuffer;
} }
const ColorDescription &EglGbmLayerSurface::colorDescription() const const ColorDescription &EglGbmLayerSurface::colorDescription() const
{ {
return m_surface.shadowTexture ? m_surface.intermediaryColorDescription : m_surface.targetColorDescription; return m_surface->shadowTexture ? m_surface->intermediaryColorDescription : m_surface->targetColorDescription;
} }
bool EglGbmLayerSurface::doesSurfaceFit(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const bool EglGbmLayerSurface::doesSurfaceFit(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const
{ {
return doesSurfaceFit(m_surface, size, formats); return doesSurfaceFit(m_surface.get(), size, formats);
} }
std::shared_ptr<GLTexture> EglGbmLayerSurface::texture() const std::shared_ptr<GLTexture> EglGbmLayerSurface::texture() const
{ {
return m_surface.shadowTexture ? m_surface.shadowTexture : m_surface.currentSlot->texture(); return m_surface->shadowTexture ? m_surface->shadowTexture : m_surface->currentSlot->texture();
} }
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats) std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap<uint32_t, QVector<uint64_t>> &formats)
{ {
if (checkSurface(bufferSize, formats)) { if (checkSurface(bufferSize, formats)) {
return m_surface.currentFramebuffer; return m_surface->currentFramebuffer;
} else { } else {
return nullptr; return nullptr;
} }
@ -220,31 +217,34 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::renderTestBuffer(const QSize
bool EglGbmLayerSurface::checkSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) bool EglGbmLayerSurface::checkSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats)
{ {
if (doesSurfaceFit(m_surface, size, formats)) { if (doesSurfaceFit(m_surface.get(), size, formats)) {
return true; return true;
} }
if (doesSurfaceFit(m_oldSurface, size, formats)) { if (doesSurfaceFit(m_oldSurface.get(), size, formats)) {
m_surface = m_oldSurface; m_surface = std::move(m_oldSurface);
return true; return true;
} }
if (const auto newSurface = createSurface(size, formats)) { if (auto newSurface = createSurface(size, formats)) {
m_oldSurface = m_surface; m_oldSurface = std::move(m_surface);
m_surface = newSurface.value(); m_surface = std::move(newSurface);
return true; return true;
} }
return false; return false;
} }
bool EglGbmLayerSurface::doesSurfaceFit(const Surface &surface, const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const bool EglGbmLayerSurface::doesSurfaceFit(Surface *surface, const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const
{ {
const auto &swapchain = surface.gbmSwapchain; if (!surface) {
return false;
}
const auto &swapchain = surface->gbmSwapchain;
return swapchain return swapchain
&& swapchain->size() == size && swapchain->size() == size
&& formats.contains(swapchain->format()) && formats.contains(swapchain->format())
&& (surface.forceLinear || swapchain->modifier() == DRM_FORMAT_MOD_INVALID || formats[swapchain->format()].contains(swapchain->modifier())); && (surface->forceLinear || swapchain->modifier() == DRM_FORMAT_MOD_INVALID || formats[swapchain->format()].contains(swapchain->modifier()));
} }
std::optional<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const std::unique_ptr<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const
{ {
QVector<FormatInfo> preferredFormats; QVector<FormatInfo> preferredFormats;
QVector<FormatInfo> fallbackFormats; QVector<FormatInfo> fallbackFormats;
@ -270,47 +270,47 @@ std::optional<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(con
return lhs.bitsPerPixel < rhs.bitsPerPixel; return lhs.bitsPerPixel < rhs.bitsPerPixel;
} }
}; };
const auto doTestFormats = [this, &size, &formats](const QVector<FormatInfo> &gbmFormats, MultiGpuImportMode importMode) -> std::optional<Surface> { const auto doTestFormats = [this, &size, &formats](const QVector<FormatInfo> &gbmFormats, MultiGpuImportMode importMode) -> std::unique_ptr<Surface> {
for (const auto &format : gbmFormats) { for (const auto &format : gbmFormats) {
if (m_formatOption == FormatOption::RequireAlpha && format.alphaBits == 0) { if (m_formatOption == FormatOption::RequireAlpha && format.alphaBits == 0) {
continue; continue;
} }
const auto surface = createSurface(size, format.drmFormat, formats[format.drmFormat], importMode); auto surface = createSurface(size, format.drmFormat, formats[format.drmFormat], importMode);
if (surface.has_value()) { if (surface) {
return surface; return surface;
} }
} }
return std::nullopt; return nullptr;
}; };
const auto testFormats = [this, &sort, &doTestFormats](QVector<FormatInfo> &formats) -> std::optional<Surface> { const auto testFormats = [this, &sort, &doTestFormats](QVector<FormatInfo> &formats) -> std::unique_ptr<Surface> {
std::sort(formats.begin(), formats.end(), sort); std::sort(formats.begin(), formats.end(), sort);
if (m_gpu == m_eglBackend->gpu()) { if (m_gpu == m_eglBackend->gpu()) {
return doTestFormats(formats, MultiGpuImportMode::None); return doTestFormats(formats, MultiGpuImportMode::None);
} }
if (const auto surface = doTestFormats(formats, MultiGpuImportMode::Egl)) { if (auto surface = doTestFormats(formats, MultiGpuImportMode::Egl)) {
qCDebug(KWIN_DRM) << "chose egl import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier(); qCDebug(KWIN_DRM) << "chose egl import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier();
return surface; return surface;
} }
if (const auto surface = doTestFormats(formats, MultiGpuImportMode::Dmabuf)) { if (auto surface = doTestFormats(formats, MultiGpuImportMode::Dmabuf)) {
qCDebug(KWIN_DRM) << "chose dmabuf import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier(); qCDebug(KWIN_DRM) << "chose dmabuf import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier();
return surface; return surface;
} }
if (const auto surface = doTestFormats(formats, MultiGpuImportMode::LinearDmabuf)) { if (auto surface = doTestFormats(formats, MultiGpuImportMode::LinearDmabuf)) {
qCDebug(KWIN_DRM) << "chose linear dmabuf import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier(); qCDebug(KWIN_DRM) << "chose linear dmabuf import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier();
return surface; return surface;
} }
if (const auto surface = doTestFormats(formats, MultiGpuImportMode::DumbBuffer)) { if (auto surface = doTestFormats(formats, MultiGpuImportMode::DumbBuffer)) {
qCDebug(KWIN_DRM) << "chose cpu import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier(); qCDebug(KWIN_DRM) << "chose cpu import with format" << formatName(surface->gbmSwapchain->format()).name << "and modifier" << surface->gbmSwapchain->modifier();
return surface; return surface;
} }
return std::nullopt; return nullptr;
}; };
if (const auto ret = testFormats(preferredFormats)) { if (auto ret = testFormats(preferredFormats)) {
return ret; return ret;
} else if (const auto ret = testFormats(fallbackFormats)) { } else if (auto ret = testFormats(fallbackFormats)) {
return ret; return ret;
} else { } else {
return std::nullopt; return nullptr;
} }
} }
@ -324,48 +324,48 @@ static QVector<uint64_t> filterModifiers(const QVector<uint64_t> &one, const QVe
return ret; return ret;
} }
std::optional<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, MultiGpuImportMode importMode) const std::unique_ptr<EglGbmLayerSurface::Surface> EglGbmLayerSurface::createSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, MultiGpuImportMode importMode) const
{ {
const bool cpuCopy = importMode == MultiGpuImportMode::DumbBuffer || m_bufferTarget == BufferTarget::Dumb; const bool cpuCopy = importMode == MultiGpuImportMode::DumbBuffer || m_bufferTarget == BufferTarget::Dumb;
QVector<uint64_t> renderModifiers; QVector<uint64_t> renderModifiers;
Surface ret; auto ret = std::make_unique<Surface>();
if (importMode == MultiGpuImportMode::Egl) { if (importMode == MultiGpuImportMode::Egl) {
ret.importContext = m_eglBackend->contextForGpu(m_gpu); ret->importContext = m_eglBackend->contextForGpu(m_gpu);
if (!ret.importContext || ret.importContext->isSoftwareRenderer()) { if (!ret->importContext || ret->importContext->isSoftwareRenderer()) {
return std::nullopt; return nullptr;
} }
renderModifiers = filterModifiers(ret.importContext->displayObject()->allSupportedDrmFormats()[format], renderModifiers = filterModifiers(ret->importContext->displayObject()->allSupportedDrmFormats()[format],
m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format)); m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format));
} else if (cpuCopy) { } else if (cpuCopy) {
if (!cpuCopyFormats.contains(format)) { if (!cpuCopyFormats.contains(format)) {
return std::nullopt; return nullptr;
} }
renderModifiers = m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format); renderModifiers = m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format);
} else { } else {
renderModifiers = filterModifiers(modifiers, m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format)); renderModifiers = filterModifiers(modifiers, m_eglBackend->eglDisplayObject()->supportedDrmFormats().value(format));
} }
if (renderModifiers.empty()) { if (renderModifiers.empty()) {
return std::nullopt; return nullptr;
} }
ret.context = m_eglBackend->contextForGpu(m_eglBackend->gpu()); ret->context = m_eglBackend->contextForGpu(m_eglBackend->gpu());
ret.importMode = importMode; ret->importMode = importMode;
ret.forceLinear = importMode == MultiGpuImportMode::DumbBuffer || importMode == MultiGpuImportMode::LinearDmabuf || m_bufferTarget != BufferTarget::Normal; ret->forceLinear = importMode == MultiGpuImportMode::DumbBuffer || importMode == MultiGpuImportMode::LinearDmabuf || m_bufferTarget != BufferTarget::Normal;
ret.gbmSwapchain = createGbmSwapchain(m_eglBackend->gpu(), m_eglBackend->contextObject(), size, format, renderModifiers, ret.forceLinear); ret->gbmSwapchain = createGbmSwapchain(m_eglBackend->gpu(), m_eglBackend->contextObject(), size, format, renderModifiers, ret->forceLinear);
if (!ret.gbmSwapchain) { if (!ret->gbmSwapchain) {
return std::nullopt; return nullptr;
} }
if (cpuCopy) { if (cpuCopy) {
ret.importDumbSwapchain = std::make_shared<QPainterSwapchain>(m_gpu->graphicsBufferAllocator(), size, format); ret->importDumbSwapchain = std::make_unique<QPainterSwapchain>(m_gpu->graphicsBufferAllocator(), size, format);
} else if (importMode == MultiGpuImportMode::Egl) { } else if (importMode == MultiGpuImportMode::Egl) {
ret.importGbmSwapchain = createGbmSwapchain(m_gpu, ret.importContext.get(), size, format, modifiers, false); ret->importGbmSwapchain = createGbmSwapchain(m_gpu, ret->importContext.get(), size, format, modifiers, false);
if (!ret.importGbmSwapchain) { if (!ret->importGbmSwapchain) {
return std::nullopt; return nullptr;
} }
ret.importTimeQuery = std::make_shared<GLRenderTimeQuery>(); ret->importTimeQuery = std::make_unique<GLRenderTimeQuery>();
} }
ret.timeQuery = std::make_shared<GLRenderTimeQuery>(); ret->timeQuery = std::make_unique<GLRenderTimeQuery>();
if (!doRenderTestBuffer(ret)) { if (!doRenderTestBuffer(ret.get())) {
return std::nullopt; return nullptr;
} }
return ret; return ret;
} }
@ -400,26 +400,26 @@ std::shared_ptr<EglSwapchain> EglGbmLayerSurface::createGbmSwapchain(DrmGpu *gpu
return EglSwapchain::create(gpu->graphicsBufferAllocator(), context, size, format, implicitModifier); return EglSwapchain::create(gpu->graphicsBufferAllocator(), context, size, format, implicitModifier);
} }
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::doRenderTestBuffer(Surface &surface) const std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::doRenderTestBuffer(Surface *surface) const
{ {
auto slot = surface.gbmSwapchain->acquire(); auto slot = surface->gbmSwapchain->acquire();
if (!slot) { if (!slot) {
return nullptr; return nullptr;
} }
if (const auto ret = importBuffer(surface, slot.get())) { if (const auto ret = importBuffer(surface, slot.get())) {
surface.currentSlot = slot; surface->currentSlot = slot;
surface.currentFramebuffer = ret; surface->currentFramebuffer = ret;
return ret; return ret;
} else { } else {
return nullptr; return nullptr;
} }
} }
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importBuffer(Surface &surface, EglSwapchainSlot *slot) const std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importBuffer(Surface *surface, EglSwapchainSlot *slot) const
{ {
if (m_bufferTarget == BufferTarget::Dumb || surface.importMode == MultiGpuImportMode::DumbBuffer) { if (m_bufferTarget == BufferTarget::Dumb || surface->importMode == MultiGpuImportMode::DumbBuffer) {
return importWithCpu(surface, slot); return importWithCpu(surface, slot);
} else if (surface.importMode == MultiGpuImportMode::Egl) { } else if (surface->importMode == MultiGpuImportMode::Egl) {
return importWithEgl(surface, slot->buffer()); return importWithEgl(surface, slot->buffer());
} else { } else {
const auto ret = m_gpu->importBuffer(slot->buffer()); const auto ret = m_gpu->importBuffer(slot->buffer());
@ -430,9 +430,9 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importBuffer(Surface &surfac
} }
} }
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface &surface, GraphicsBuffer *sourceBuffer) const std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer) const
{ {
Q_ASSERT(surface.importGbmSwapchain); Q_ASSERT(surface->importGbmSwapchain);
EGLNativeFence sourceFence(m_eglBackend->eglDisplayObject()); EGLNativeFence sourceFence(m_eglBackend->eglDisplayObject());
@ -441,25 +441,25 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface &surfa
if (!sourceFence.isValid() || !display->supportsNativeFence()) { if (!sourceFence.isValid() || !display->supportsNativeFence()) {
glFinish(); glFinish();
} }
if (!surface.importContext->makeCurrent()) { if (!surface->importContext->makeCurrent()) {
return nullptr; return nullptr;
} }
surface.importTimeQuery->begin(); surface->importTimeQuery->begin();
if (sourceFence.isValid()) { if (sourceFence.isValid()) {
const auto destinationFence = EGLNativeFence::importFence(surface.importContext->displayObject(), sourceFence.fileDescriptor().duplicate()); const auto destinationFence = EGLNativeFence::importFence(surface->importContext->displayObject(), sourceFence.fileDescriptor().duplicate());
destinationFence.waitSync(); destinationFence.waitSync();
} }
auto &sourceTexture = surface.importedTextureCache[sourceBuffer]; auto &sourceTexture = surface->importedTextureCache[sourceBuffer];
if (!sourceTexture) { if (!sourceTexture) {
sourceTexture = surface.importContext->importDmaBufAsTexture(*sourceBuffer->dmabufAttributes()); sourceTexture = surface->importContext->importDmaBufAsTexture(*sourceBuffer->dmabufAttributes());
} }
if (!sourceTexture) { if (!sourceTexture) {
qCWarning(KWIN_DRM, "failed to import the source texture!"); qCWarning(KWIN_DRM, "failed to import the source texture!");
return nullptr; return nullptr;
} }
auto slot = surface.importGbmSwapchain->acquire(); auto slot = surface->importGbmSwapchain->acquire();
if (!slot) { if (!slot) {
qCWarning(KWIN_DRM, "failed to import the local texture!"); qCWarning(KWIN_DRM, "failed to import the local texture!");
return nullptr; return nullptr;
@ -469,7 +469,7 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface &surfa
glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle()); glBindFramebuffer(GL_FRAMEBUFFER, fbo->handle());
glViewport(0, 0, fbo->size().width(), fbo->size().height()); 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;
mat.scale(1, -1); mat.scale(1, -1);
mat.ortho(QRect(QPoint(), fbo->size())); mat.ortho(QRect(QPoint(), fbo->size()));
@ -481,20 +481,20 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithEgl(Surface &surfa
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
surface.importContext->shaderManager()->popShader(); surface->importContext->shaderManager()->popShader();
glFlush(); glFlush();
surface.importGbmSwapchain->release(slot); surface->importGbmSwapchain->release(slot);
surface.importTimeQuery->end(); surface->importTimeQuery->end();
// restore the old context // restore the old context
m_eglBackend->makeCurrent(); m_eglBackend->makeCurrent();
return m_gpu->importBuffer(slot->buffer()); return m_gpu->importBuffer(slot->buffer());
} }
std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithCpu(Surface &surface, EglSwapchainSlot *source) const std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithCpu(Surface *surface, EglSwapchainSlot *source) const
{ {
Q_ASSERT(surface.importDumbSwapchain); Q_ASSERT(surface->importDumbSwapchain);
const auto slot = surface.importDumbSwapchain->acquire(); const auto slot = surface->importDumbSwapchain->acquire();
if (!slot) { if (!slot) {
qCWarning(KWIN_DRM) << "EglGbmLayerSurface::importWithCpu: failed to get a target dumb buffer"; qCWarning(KWIN_DRM) << "EglGbmLayerSurface::importWithCpu: failed to get a target dumb buffer";
return nullptr; return nullptr;
@ -507,12 +507,12 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithCpu(Surface &surfa
glReadPixels(0, 0, dst->width(), dst->height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dst->bits()); glReadPixels(0, 0, dst->width(), dst->height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, dst->bits());
} else { } else {
// there's padding, need to copy line by line // there's padding, need to copy line by line
if (surface.cpuCopyCache.size() != dst->size()) { if (surface->cpuCopyCache.size() != dst->size()) {
surface.cpuCopyCache = QImage(dst->size(), QImage::Format_RGBA8888); surface->cpuCopyCache = QImage(dst->size(), QImage::Format_RGBA8888);
} }
glReadPixels(0, 0, dst->width(), dst->height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface.cpuCopyCache.bits()); glReadPixels(0, 0, dst->width(), dst->height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface->cpuCopyCache.bits());
for (int i = 0; i < dst->height(); i++) { for (int i = 0; i < dst->height(); i++) {
std::memcpy(dst->scanLine(i), surface.cpuCopyCache.scanLine(i), srcStride); std::memcpy(dst->scanLine(i), surface->cpuCopyCache.scanLine(i), srcStride);
} }
} }
GLFramebuffer::popFramebuffer(); GLFramebuffer::popFramebuffer();
@ -521,7 +521,7 @@ std::shared_ptr<DrmFramebuffer> EglGbmLayerSurface::importWithCpu(Surface &surfa
if (!ret) { if (!ret) {
qCWarning(KWIN_DRM, "Failed to create a framebuffer: %s", strerror(errno)); qCWarning(KWIN_DRM, "Failed to create a framebuffer: %s", strerror(errno));
} }
surface.importDumbSwapchain->release(slot); surface->importDumbSwapchain->release(slot);
return ret; return ret;
} }
} }

View file

@ -81,14 +81,14 @@ private:
std::shared_ptr<EglContext> context; std::shared_ptr<EglContext> context;
bool colormanagementEnabled = false; bool colormanagementEnabled = false;
std::shared_ptr<GLTexture> shadowTexture; std::shared_ptr<GLTexture> shadowTexture;
std::shared_ptr<GLFramebuffer> shadowBuffer; std::unique_ptr<GLFramebuffer> shadowBuffer;
ColorDescription targetColorDescription = ColorDescription::sRGB; ColorDescription targetColorDescription = ColorDescription::sRGB;
ColorDescription intermediaryColorDescription = ColorDescription::sRGB; ColorDescription intermediaryColorDescription = ColorDescription::sRGB;
QVector3D channelFactors = {1, 1, 1}; QVector3D channelFactors = {1, 1, 1};
std::shared_ptr<EglSwapchain> gbmSwapchain; std::shared_ptr<EglSwapchain> gbmSwapchain;
std::shared_ptr<EglSwapchainSlot> currentSlot; std::shared_ptr<EglSwapchainSlot> currentSlot;
DamageJournal damageJournal; DamageJournal damageJournal;
std::shared_ptr<QPainterSwapchain> importDumbSwapchain; std::unique_ptr<QPainterSwapchain> importDumbSwapchain;
std::shared_ptr<EglContext> importContext; std::shared_ptr<EglContext> importContext;
std::shared_ptr<EglSwapchain> importGbmSwapchain; std::shared_ptr<EglSwapchain> importGbmSwapchain;
QHash<GraphicsBuffer *, std::shared_ptr<GLTexture>> importedTextureCache; QHash<GraphicsBuffer *, std::shared_ptr<GLTexture>> importedTextureCache;
@ -98,24 +98,24 @@ private:
bool forceLinear = false; bool forceLinear = false;
// for render timing // for render timing
std::shared_ptr<GLRenderTimeQuery> timeQuery; std::unique_ptr<GLRenderTimeQuery> timeQuery;
std::shared_ptr<GLRenderTimeQuery> importTimeQuery; std::unique_ptr<GLRenderTimeQuery> importTimeQuery;
std::chrono::steady_clock::time_point renderStart; std::chrono::steady_clock::time_point renderStart;
std::chrono::steady_clock::time_point renderEnd; std::chrono::steady_clock::time_point renderEnd;
}; };
bool checkSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats); bool checkSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats);
bool doesSurfaceFit(const Surface &surface, const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const; bool doesSurfaceFit(Surface *surface, const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const;
std::optional<Surface> createSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const; std::unique_ptr<Surface> createSurface(const QSize &size, const QMap<uint32_t, QVector<uint64_t>> &formats) const;
std::optional<Surface> createSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, MultiGpuImportMode importMode) const; std::unique_ptr<Surface> createSurface(const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, MultiGpuImportMode importMode) const;
std::shared_ptr<EglSwapchain> createGbmSwapchain(DrmGpu *gpu, EglContext *context, const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, bool forceLinear) const; std::shared_ptr<EglSwapchain> createGbmSwapchain(DrmGpu *gpu, EglContext *context, const QSize &size, uint32_t format, const QVector<uint64_t> &modifiers, bool forceLinear) 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) const; std::shared_ptr<DrmFramebuffer> importBuffer(Surface *surface, EglSwapchainSlot *source) const;
std::shared_ptr<DrmFramebuffer> importWithEgl(Surface &surface, GraphicsBuffer *sourceBuffer) const; std::shared_ptr<DrmFramebuffer> importWithEgl(Surface *surface, GraphicsBuffer *sourceBuffer) const;
std::shared_ptr<DrmFramebuffer> importWithCpu(Surface &surface, EglSwapchainSlot *source) const; std::shared_ptr<DrmFramebuffer> importWithCpu(Surface *surface, EglSwapchainSlot *source) const;
Surface m_surface; std::unique_ptr<Surface> m_surface;
Surface m_oldSurface; std::unique_ptr<Surface> m_oldSurface;
DrmGpu *const m_gpu; DrmGpu *const m_gpu;
EglGbmBackend *const m_eglBackend; EglGbmBackend *const m_eglBackend;