backends/drm: don't crash if beginFrame fails
CCBUG: 455532
This commit is contained in:
parent
8feaa8922a
commit
9f41620b77
29 changed files with 62 additions and 60 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -36,7 +36,7 @@ EglGbmLayer::EglGbmLayer(EglGbmBackend *eglBackend, DrmPipeline *pipeline)
|
|||
{
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo EglGbmLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> EglGbmLayer::beginFrame()
|
||||
{
|
||||
m_scanoutBuffer.reset();
|
||||
m_dmabufFeedback.renderingSurface();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ GLTexture *VirtualEglLayer::texture() const
|
|||
return m_texture.get();
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo VirtualEglLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> VirtualEglLayer::beginFrame()
|
||||
{
|
||||
m_backend->makeCurrent();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -142,7 +142,7 @@ bool WaylandEglOutput::makeContextCurrent() const
|
|||
return true;
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo WaylandEglOutput::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> WaylandEglOutput::beginFrame()
|
||||
{
|
||||
eglWaitNative(EGL_CORE_NATIVE_ENGINE);
|
||||
makeContextCurrent();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -32,7 +32,7 @@ EglLayer::EglLayer(EglBackend *backend)
|
|||
{
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo EglLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> EglLayer::beginFrame()
|
||||
{
|
||||
return m_backend->beginFrame();
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -109,7 +109,7 @@ GlxLayer::GlxLayer(GlxBackend *backend)
|
|||
{
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo GlxLayer::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> GlxLayer::beginFrame()
|
||||
{
|
||||
return m_backend->beginFrame();
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -30,7 +30,7 @@ void X11WindowedQPainterOutput::ensureBuffer()
|
|||
}
|
||||
}
|
||||
|
||||
OutputLayerBeginFrameInfo X11WindowedQPainterOutput::beginFrame()
|
||||
std::optional<OutputLayerBeginFrameInfo> X11WindowedQPainterOutput::beginFrame()
|
||||
{
|
||||
ensureBuffer();
|
||||
return OutputLayerBeginFrameInfo{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue