backends/drm: don't crash if beginFrame fails

CCBUG: 455532
This commit is contained in:
Xaver Hugl 2022-08-04 18:14:37 +02:00
parent 8feaa8922a
commit 9f41620b77
29 changed files with 62 additions and 60 deletions

View file

@ -22,7 +22,7 @@ EglGbmCursorLayer::EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pip
{
}
OutputLayerBeginFrameInfo EglGbmCursorLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> EglGbmCursorLayer::beginFrame()
{
// some legacy drivers don't work with linear gbm buffers for the cursor
const auto target = m_pipeline->gpu()->atomicModeSetting() ? EglGbmLayerSurface::BufferTarget::Linear : EglGbmLayerSurface::BufferTarget::Dumb;

View file

@ -29,7 +29,7 @@ class EglGbmCursorLayer : public DrmOverlayLayer
public:
EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
void aboutToStartPainting(const QRegion &damagedRegion) override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;

View file

@ -36,7 +36,7 @@ EglGbmLayer::EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline)
{
}
OutputLayerBeginFrameInfo EglGbmLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::beginFrame()
{
m_scanoutBuffer.reset();
m_dmabufFeedback.renderingSurface();

View file

@ -29,7 +29,7 @@ class EglGbmLayer : public DrmPipelineLayer
public:
EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
void aboutToStartPainting(const QRegion &damagedRegion) override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;

View file

@ -55,13 +55,13 @@ void EglGbmLayerSurface::destroyResources()
m_oldGbmSurface.reset();
}
OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target)
std::optional<OutputLayerBeginFrameInfo> EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target)
{
if (!checkGbmSurface(bufferSize, formats, target == BufferTarget::Linear)) {
return {};
return std::nullopt;
}
if (!m_gbmSurface->makeContextCurrent()) {
return {};
return std::nullopt;
}
// shadow buffer
@ -75,11 +75,11 @@ OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &buffer
if (renderOrientation != bufferOrientation) {
const auto format = m_eglBackend->gbmFormatForDrmFormat(m_gbmSurface->format());
if (!format.has_value()) {
return {};
return std::nullopt;
}
m_shadowBuffer = std::make_shared<ShadowBuffer>(renderSize, format.value());
if (!m_shadowBuffer->isComplete()) {
return {};
return std::nullopt;
}
} else {
m_shadowBuffer.reset();

View file

@ -46,7 +46,7 @@ public:
Linear,
Dumb
};
OutputLayerBeginFrameInfo startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target = BufferTarget::Normal);
std::optional<OutputLayerBeginFrameInfo> startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap<uint32_t, QVector<uint64_t>> &formats, BufferTarget target = BufferTarget::Normal);
void aboutToStartPainting(DrmOutput *output, const QRegion &damagedRegion);
std::optional<std::tuple<std::shared_ptr<DrmFramebuffer>, QRegion>> endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion, BufferTarget target = BufferTarget::Normal);

View file

@ -165,27 +165,26 @@ void DrmOutput::updateCursor()
}
return;
}
bool rendered = false;
const QMatrix4x4 monitorMatrix = logicalToNativeMatrix(geometry(), scale(), transform());
const QRect cursorRect = monitorMatrix.mapRect(cursor->geometry());
if (cursorRect.width() > m_gpu->cursorSize().width() || cursorRect.height() > m_gpu->cursorSize().height()) {
if (cursorRect.width() <= m_gpu->cursorSize().width() && cursorRect.height() <= m_gpu->cursorSize().height()) {
if (const auto beginInfo = layer->beginFrame()) {
const auto &[renderTarget, repaint] = beginInfo.value();
if (dynamic_cast<EglGbmBackend *>(m_gpu->platform()->renderBackend())) {
renderCursorOpengl(renderTarget, cursor->geometry().size() * scale());
} else {
renderCursorQPainter(renderTarget);
}
rendered = layer->endFrame(infiniteRegion(), infiniteRegion());
}
}
if (!rendered) {
if (layer->isVisible()) {
layer->setVisible(false);
m_pipeline->setCursor();
}
m_setCursorSuccessful = false;
return;
}
const auto [renderTarget, repaint] = layer->beginFrame();
if (dynamic_cast<EglGbmBackend *>(m_gpu->platform()->renderBackend())) {
renderCursorOpengl(renderTarget, cursor->geometry().size() * scale());
} else {
renderCursorQPainter(renderTarget);
}
bool rendered = layer->endFrame(infiniteRegion(), infiniteRegion());
if (!rendered) {
m_setCursorSuccessful = false;
layer->setVisible(false);
return;
}
const QSize surfaceSize = m_gpu->cursorSize() / scale();

View file

@ -29,14 +29,14 @@ DrmQPainterLayer::DrmQPainterLayer(DrmPipeline *pipeline)
{
}
OutputLayerBeginFrameInfo DrmQPainterLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> DrmQPainterLayer::beginFrame()
{
if (!doesSwapchainFit()) {
m_swapchain = std::make_shared<DumbSwapchain>(m_pipeline->gpu(), m_pipeline->bufferSize(), DRM_FORMAT_XRGB8888);
}
QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(&needsRepaint)) {
return {};
return std::nullopt;
}
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_swapchain->currentBuffer()->image()),
@ -97,14 +97,14 @@ DrmCursorQPainterLayer::DrmCursorQPainterLayer(DrmPipeline *pipeline)
{
}
OutputLayerBeginFrameInfo DrmCursorQPainterLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> DrmCursorQPainterLayer::beginFrame()
{
if (!m_swapchain) {
m_swapchain = std::make_shared<DumbSwapchain>(m_pipeline->gpu(), m_pipeline->gpu()->cursorSize(), DRM_FORMAT_ARGB8888);
}
QRegion needsRepaint;
if (!m_swapchain->acquireBuffer(&needsRepaint)) {
return {};
return std::nullopt;
}
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(m_swapchain->currentBuffer()->image()),
@ -148,7 +148,7 @@ DrmVirtualQPainterLayer::DrmVirtualQPainterLayer(DrmVirtualOutput *output)
{
}
OutputLayerBeginFrameInfo DrmVirtualQPainterLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> DrmVirtualQPainterLayer::beginFrame()
{
if (m_image.isNull() || m_image.size() != m_output->pixelSize()) {
m_image = QImage(m_output->pixelSize(), QImage::Format_RGB32);

View file

@ -26,7 +26,7 @@ class DrmQPainterLayer : public DrmPipelineLayer
public:
DrmQPainterLayer(DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
bool checkTestBuffer() override;
std::shared_ptr<DrmFramebuffer> currentBuffer() const override;
@ -46,7 +46,7 @@ class DrmCursorQPainterLayer : public DrmOverlayLayer
public:
DrmCursorQPainterLayer(DrmPipeline *pipeline);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
bool checkTestBuffer() override;
@ -64,7 +64,7 @@ class DrmVirtualQPainterLayer : public DrmOutputLayer
public:
DrmVirtualQPainterLayer(DrmVirtualOutput *output);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &damagedRegion, const QRegion &renderedRegion) override;
QRegion currentDamage() const override;

View file

@ -52,7 +52,7 @@ void VirtualEglGbmLayer::aboutToStartPainting(const QRegion &damagedRegion)
}
}
OutputLayerBeginFrameInfo VirtualEglGbmLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> VirtualEglGbmLayer::beginFrame()
{
// gbm surface
if (doesGbmSurfaceFit(m_gbmSurface.get())) {
@ -62,12 +62,12 @@ OutputLayerBeginFrameInfo VirtualEglGbmLayer::beginFrame()
m_gbmSurface = m_oldGbmSurface;
} else {
if (!createGbmSurface()) {
return {};
return std::nullopt;
}
}
}
if (!m_gbmSurface->makeContextCurrent()) {
return {};
return std::nullopt;
}
GLFramebuffer::pushFramebuffer(m_gbmSurface->fbo());
return OutputLayerBeginFrameInfo{

View file

@ -35,7 +35,7 @@ public:
VirtualEglGbmLayer(EglGbmBackend *eglBackend, DrmVirtualOutput *output);
void aboutToStartPainting(const QRegion &damagedRegion) override;
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
bool scanout(SurfaceItem *surfaceItem) override;

View file

@ -37,7 +37,7 @@ GLTexture *VirtualEglLayer::texture() const
return m_texture.get();
}
OutputLayerBeginFrameInfo VirtualEglLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> VirtualEglLayer::beginFrame()
{
m_backend->makeCurrent();

View file

@ -24,7 +24,7 @@ public:
VirtualEglLayer(Output *output, VirtualEglBackend *backend);
~VirtualEglLayer() override;
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
GLTexture *texture() const;

View file

@ -23,7 +23,7 @@ VirtualQPainterLayer::VirtualQPainterLayer(Output *output)
m_image.fill(Qt::black);
}
OutputLayerBeginFrameInfo VirtualQPainterLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> VirtualQPainterLayer::beginFrame()
{
return OutputLayerBeginFrameInfo{
.renderTarget = RenderTarget(&m_image),

View file

@ -26,7 +26,7 @@ class VirtualQPainterLayer : public OutputLayer
public:
VirtualQPainterLayer(Output *output);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
QImage *image();
@ -54,4 +54,4 @@ private:
int m_frameCounter = 0;
};
} // namespace KWin
} // namespace KWin

View file

@ -142,7 +142,7 @@ bool WaylandEglOutput::makeContextCurrent() const
return true;
}
OutputLayerBeginFrameInfo WaylandEglOutput::beginFrame()
std::optional<OutputLayerBeginFrameInfo> WaylandEglOutput::beginFrame()
{
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
makeContextCurrent();

View file

@ -47,7 +47,7 @@ public:
bool makeContextCurrent() const;
void present();
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
void aboutToStartPainting(const QRegion &damage) override;

View file

@ -127,7 +127,7 @@ QRegion WaylandQPainterOutput::accumulateDamage(int bufferAge) const
return m_damageJournal.accumulate(bufferAge, infiniteRegion());
}
OutputLayerBeginFrameInfo WaylandQPainterOutput::beginFrame()
std::optional<OutputLayerBeginFrameInfo> WaylandQPainterOutput::beginFrame()
{
WaylandQPainterBufferSlot *slot = acquire();
return OutputLayerBeginFrameInfo{

View file

@ -52,7 +52,7 @@ public:
WaylandQPainterOutput(WaylandOutput *output);
~WaylandQPainterOutput() override;
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
bool init(KWayland::Client::ShmPool *pool);

View file

@ -32,7 +32,7 @@ EglLayer::EglLayer(EglBackend *backend)
{
}
OutputLayerBeginFrameInfo EglLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> EglLayer::beginFrame()
{
return m_backend->beginFrame();
}

View file

@ -27,7 +27,7 @@ class EglLayer : public OutputLayer
public:
EglLayer(EglBackend *backend);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
private:

View file

@ -109,7 +109,7 @@ GlxLayer::GlxLayer(GlxBackend *backend)
{
}
OutputLayerBeginFrameInfo GlxLayer::beginFrame()
std::optional<OutputLayerBeginFrameInfo> GlxLayer::beginFrame()
{
return m_backend->beginFrame();
}

View file

@ -64,7 +64,7 @@ class GlxLayer : public OutputLayer
public:
GlxLayer(GlxBackend *backend);
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
private:

View file

@ -38,7 +38,7 @@ void X11WindowedEglOutput::ensureFbo()
}
}
OutputLayerBeginFrameInfo X11WindowedEglOutput::beginFrame()
std::optional<OutputLayerBeginFrameInfo> X11WindowedEglOutput::beginFrame()
{
eglMakeCurrent(m_backend->eglDisplay(), m_eglSurface, m_eglSurface, m_backend->context());
ensureFbo();

View file

@ -26,7 +26,7 @@ public:
X11WindowedEglOutput(X11WindowedEglBackend *backend, Output *output, EGLSurface surface);
~X11WindowedEglOutput();
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
EGLSurface surface() const;
QRegion lastDamage() const;

View file

@ -30,7 +30,7 @@ void X11WindowedQPainterOutput::ensureBuffer()
}
}
OutputLayerBeginFrameInfo X11WindowedQPainterOutput::beginFrame()
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterOutput::beginFrame()
{
ensureBuffer();
return OutputLayerBeginFrameInfo{

View file

@ -31,7 +31,7 @@ public:
void ensureBuffer();
OutputLayerBeginFrameInfo beginFrame() override;
std::optional<OutputLayerBeginFrameInfo> beginFrame() override;
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override;
xcb_window_t window;

View file

@ -646,14 +646,16 @@ void Compositor::composite(RenderLoop *renderLoop)
outputLayer->resetRepaints();
preparePaintPass(superLayer, &surfaceDamage);
OutputLayerBeginFrameInfo beginInfo = outputLayer->beginFrame();
beginInfo.renderTarget.setDevicePixelRatio(output->scale());
if (auto beginInfo = outputLayer->beginFrame()) {
auto &[renderTarget, repaint] = beginInfo.value();
renderTarget.setDevicePixelRatio(output->scale());
const QRegion bufferDamage = surfaceDamage.united(beginInfo.repaint).intersected(superLayer->rect());
outputLayer->aboutToStartPainting(bufferDamage);
const QRegion bufferDamage = surfaceDamage.united(repaint).intersected(superLayer->rect());
outputLayer->aboutToStartPainting(bufferDamage);
paintPass(superLayer, &beginInfo.renderTarget, bufferDamage);
outputLayer->endFrame(bufferDamage, surfaceDamage);
paintPass(superLayer, &renderTarget, bufferDamage);
outputLayer->endFrame(bufferDamage, surfaceDamage);
}
}
renderLoop->endFrame();

View file

@ -11,6 +11,7 @@
#include <QObject>
#include <QRegion>
#include <optional>
namespace KWin
{
@ -40,7 +41,7 @@ public:
*/
virtual void aboutToStartPainting(const QRegion &damage);
virtual OutputLayerBeginFrameInfo beginFrame() = 0;
virtual std::optional<OutputLayerBeginFrameInfo> beginFrame() = 0;
virtual bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) = 0;
/**