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:
parent
b266b08145
commit
88ab958f4d
2 changed files with 137 additions and 137 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue