diff --git a/src/plugins/platforms/drm/egl_stream_backend.cpp b/src/plugins/platforms/drm/egl_stream_backend.cpp index 0b7038990d..578b902a2e 100644 --- a/src/plugins/platforms/drm/egl_stream_backend.cpp +++ b/src/plugins/platforms/drm/egl_stream_backend.cpp @@ -306,6 +306,7 @@ bool EglStreamBackend::resetOutput(Output &o) if (isPrimary()) { // dumb buffer used for modesetting o.buffer = QSharedPointer::create(m_gpu, sourceSize); + o.targetPlane = drmOutput->pipeline()->primaryPlane(); EGLAttrib streamAttribs[] = { EGL_STREAM_FIFO_LENGTH_KHR, 0, // mailbox mode @@ -319,13 +320,8 @@ bool EglStreamBackend::resetOutput(Output &o) } EGLAttrib outputAttribs[3]; - if (drmOutput->pipeline()->primaryPlane()) { - outputAttribs[0] = EGL_DRM_PLANE_EXT; - outputAttribs[1] = drmOutput->pipeline()->primaryPlane()->id(); - } else { - outputAttribs[0] = EGL_DRM_CRTC_EXT; - outputAttribs[1] = drmOutput->pipeline()->crtc()->id(); - } + outputAttribs[0] = EGL_DRM_PLANE_EXT; + outputAttribs[1] = o.targetPlane->id(); outputAttribs[2] = EGL_NONE; EGLint numLayers; EGLOutputLayerEXT outputLayer; @@ -392,12 +388,6 @@ bool EglStreamBackend::addOutput(DrmAbstractOutput *output) if (!isPrimary() && !renderingBackend()->addOutput(drmOutput)) { return false; } - - connect(drmOutput, &DrmOutput::currentModeChanged, this, - [drmOutput, this] { - resetOutput(m_outputs[drmOutput]); - } - ); m_outputs.insert(output, o); return true; } else { @@ -483,11 +473,34 @@ PlatformSurfaceTexture *EglStreamBackend::createPlatformSurfaceTextureWayland(Su return new EglStreamSurfaceTextureWayland(this, pixmap); } +bool EglStreamBackend::needsReset(const Output &o) const +{ + if (o.targetPlane != o.output->pipeline()->primaryPlane()) { + return true; + } + QSize surfaceSize = o.dumbSwapchain ? o.dumbSwapchain->size() : o.buffer->size(); + if (surfaceSize != o.output->sourceSize()) { + return true; + } + bool needsTexture = surfaceSize != o.output->pixelSize(); + if (needsTexture) { + return !o.shadowBuffer || o.shadowBuffer->textureSize() != o.output->pixelSize(); + } else { + return o.shadowBuffer != nullptr; + } +} + QRegion EglStreamBackend::beginFrame(AbstractOutput *drmOutput) { Q_ASSERT(m_outputs.contains(drmOutput)); - const Output &o = m_outputs[drmOutput]; + Output &o = m_outputs[drmOutput]; if (isPrimary()) { + if (needsReset(o)) { + if (!resetOutput(o)) { + // handle this better? + return {}; + } + } makeContextCurrent(o); if (o.shadowBuffer) { o.shadowBuffer->bind(); diff --git a/src/plugins/platforms/drm/egl_stream_backend.h b/src/plugins/platforms/drm/egl_stream_backend.h index 91c40adad9..c1f0c4447e 100644 --- a/src/plugins/platforms/drm/egl_stream_backend.h +++ b/src/plugins/platforms/drm/egl_stream_backend.h @@ -21,6 +21,8 @@ class DrmAbstractOutput; class DrmDumbBuffer; class DumbSwapchain; class ShadowBuffer; +class DrmCrtc; +class DrmPlane; /** * @brief OpenGL Backend using Egl with an EGLDevice. @@ -68,12 +70,16 @@ private: EGLStreamKHR eglStream = EGL_NO_STREAM_KHR; QSharedPointer shadowBuffer; + DrmPlane *targetPlane = nullptr; + // for operation as secondary GPU QSharedPointer dumbSwapchain; }; bool resetOutput(Output &output); + bool createEglSurface(Output &o); bool makeContextCurrent(const Output &output); void cleanupOutput(Output &output); + bool needsReset(const Output &o) const; QMap m_outputs; KWaylandServer::EglStreamControllerInterface *m_eglStreamControllerInterface;