diff --git a/src/backends/drm/egl_gbm_cursor_layer.cpp b/src/backends/drm/egl_gbm_cursor_layer.cpp index b716159ff3..fb1497ae57 100644 --- a/src/backends/drm/egl_gbm_cursor_layer.cpp +++ b/src/backends/drm/egl_gbm_cursor_layer.cpp @@ -24,7 +24,9 @@ EglGbmCursorLayer::EglGbmCursorLayer(EglGbmBackend *eglBackend, DrmPipeline *pip OutputLayerBeginFrameInfo EglGbmCursorLayer::beginFrame() { - return m_surface.startRendering(m_pipeline->gpu()->cursorSize(), m_pipeline->renderOrientation(), DrmPlane::Transformation::Rotate0, m_pipeline->cursorFormats(), GBM_BO_USE_LINEAR); + // 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; + return m_surface.startRendering(m_pipeline->gpu()->cursorSize(), m_pipeline->renderOrientation(), DrmPlane::Transformation::Rotate0, m_pipeline->cursorFormats(), target); } void EglGbmCursorLayer::aboutToStartPainting(const QRegion &damagedRegion) @@ -35,7 +37,9 @@ void EglGbmCursorLayer::aboutToStartPainting(const QRegion &damagedRegion) bool EglGbmCursorLayer::endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) { Q_UNUSED(renderedRegion) - const auto ret = m_surface.endRendering(m_pipeline->renderOrientation(), damagedRegion); + // 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; + const auto ret = m_surface.endRendering(m_pipeline->renderOrientation(), damagedRegion, target); if (ret.has_value()) { QRegion throwaway; std::tie(m_currentBuffer, throwaway) = ret.value(); diff --git a/src/backends/drm/egl_gbm_layer_surface.cpp b/src/backends/drm/egl_gbm_layer_surface.cpp index 432ca44bf8..debc602fe7 100644 --- a/src/backends/drm/egl_gbm_layer_surface.cpp +++ b/src/backends/drm/egl_gbm_layer_surface.cpp @@ -55,9 +55,9 @@ void EglGbmLayerSurface::destroyResources() m_oldGbmSurface.reset(); } -OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap> &formats, uint32_t additionalFlags) +OutputLayerBeginFrameInfo EglGbmLayerSurface::startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap> &formats, BufferTarget target) { - if (!checkGbmSurface(bufferSize, formats, additionalFlags)) { + if (!checkGbmSurface(bufferSize, formats, target == BufferTarget::Linear)) { return {}; } if (!m_gbmSurface->makeContextCurrent()) { @@ -118,7 +118,7 @@ void EglGbmLayerSurface::aboutToStartPainting(DrmOutput *output, const QRegion & } } -std::optional, QRegion>> EglGbmLayerSurface::endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion) +std::optional, QRegion>> EglGbmLayerSurface::endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion, BufferTarget target) { if (m_shadowBuffer) { GLFramebuffer::popFramebuffer(); @@ -126,7 +126,7 @@ std::optional, QRegion>> EglGbmLayerS m_shadowBuffer->render(renderOrientation); } GLFramebuffer::popFramebuffer(); - if (m_gpu == m_eglBackend->gpu()) { + if (m_gpu == m_eglBackend->gpu() && target != BufferTarget::Dumb) { if (const auto buffer = m_gbmSurface->swapBuffers(damagedRegion)) { m_currentBuffer = buffer; auto ret = DrmFramebuffer::createFramebuffer(buffer); @@ -138,7 +138,7 @@ std::optional, QRegion>> EglGbmLayerS } else { if (const auto gbmBuffer = m_gbmSurface->swapBuffers(damagedRegion)) { m_currentBuffer = gbmBuffer; - const auto buffer = importBuffer(); + const auto buffer = target == BufferTarget::Dumb ? importWithCpu() : importBuffer(); if (buffer) { return std::tuple(buffer, damagedRegion); } @@ -147,7 +147,7 @@ std::optional, QRegion>> EglGbmLayerS return {}; } -bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap> &formats, uint32_t flags) +bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap> &formats, bool forceLinear) { if (doesGbmSurfaceFit(m_gbmSurface.get(), bufferSize, formats)) { m_oldGbmSurface.reset(); @@ -155,7 +155,7 @@ bool EglGbmLayerSurface::checkGbmSurface(const QSize &bufferSize, const QMap &modifiers, uint32_t flags) +bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, const QVector &modifiers, bool forceLinear) { static bool modifiersEnvSet = false; static const bool modifiersEnv = qEnvironmentVariableIntValue("KWIN_DRM_USE_MODIFIERS", &modifiersEnvSet) != 0; @@ -190,10 +190,11 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, co return false; } } - int gbmFlags = flags | GBM_BO_USE_RENDERING; + uint32_t gbmFlags = GBM_BO_USE_RENDERING; if (m_gpu == m_eglBackend->gpu()) { gbmFlags |= GBM_BO_USE_SCANOUT; - } else { + } + if (forceLinear || m_gpu != m_eglBackend->gpu()) { gbmFlags |= GBM_BO_USE_LINEAR; } const auto ret = GbmSurface::createSurface(m_eglBackend, size, format, gbmFlags, config); @@ -206,7 +207,7 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, uint32_t format, co } } -bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap> &formats, uint32_t flags) +bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap> &formats, bool forceLinear) { QVector sortedFormats; for (auto it = formats.begin(); it != formats.end(); it++) { @@ -231,7 +232,7 @@ bool EglGbmLayerSurface::createGbmSurface(const QSize &size, const QMap EglGbmLayerSurface::texture() const return m_eglBackend->importBufferObjectAsTexture(m_currentBuffer->bo()); } -std::shared_ptr EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap> &formats, uint32_t additionalFlags) +std::shared_ptr EglGbmLayerSurface::renderTestBuffer(const QSize &bufferSize, const QMap> &formats, BufferTarget target) { - if (!checkGbmSurface(bufferSize, formats, additionalFlags) || !m_gbmSurface->makeContextCurrent()) { + if (!checkGbmSurface(bufferSize, formats, target == BufferTarget::Linear) || !m_gbmSurface->makeContextCurrent()) { return nullptr; } glClear(GL_COLOR_BUFFER_BIT); @@ -365,13 +366,13 @@ std::shared_ptr EglGbmLayerSurface::renderTestBuffer(const QSize if (m_currentBuffer) { if (m_gpu != m_eglBackend->gpu()) { auto oldImportMode = m_importMode; - auto buffer = importBuffer(); + auto buffer = target == BufferTarget::Dumb ? importWithCpu() : importBuffer(); if (buffer) { return buffer; } else if (m_importMode != oldImportMode) { // try again with the new import mode // recursion depth is limited by the number of import modes - return renderTestBuffer(bufferSize, formats, additionalFlags); + return renderTestBuffer(bufferSize, formats); } else { return nullptr; } diff --git a/src/backends/drm/egl_gbm_layer_surface.h b/src/backends/drm/egl_gbm_layer_surface.h index 567f306fe3..1e1c731ec1 100644 --- a/src/backends/drm/egl_gbm_layer_surface.h +++ b/src/backends/drm/egl_gbm_layer_surface.h @@ -41,20 +41,25 @@ public: EglGbmLayerSurface(DrmGpu *gpu, EglGbmBackend *eglBackend); ~EglGbmLayerSurface(); - OutputLayerBeginFrameInfo startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap> &formats, uint32_t additionalFlags = 0); + enum class BufferTarget { + Normal, + Linear, + Dumb + }; + OutputLayerBeginFrameInfo startRendering(const QSize &bufferSize, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation, const QMap> &formats, BufferTarget target = BufferTarget::Normal); void aboutToStartPainting(DrmOutput *output, const QRegion &damagedRegion); - std::optional, QRegion>> endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion); + std::optional, QRegion>> endRendering(DrmPlane::Transformations renderOrientation, const QRegion &damagedRegion, BufferTarget target = BufferTarget::Normal); bool doesSurfaceFit(const QSize &size, const QMap> &formats) const; std::shared_ptr texture() const; void destroyResources(); EglGbmBackend *eglBackend() const; - std::shared_ptr renderTestBuffer(const QSize &bufferSize, const QMap> &formats, uint32_t additionalFlags = 0); + std::shared_ptr renderTestBuffer(const QSize &bufferSize, const QMap> &formats, BufferTarget target = BufferTarget::Normal); private: - bool checkGbmSurface(const QSize &size, const QMap> &formats, uint32_t flags); - bool createGbmSurface(const QSize &size, uint32_t format, const QVector &modifiers, uint32_t flags); - bool createGbmSurface(const QSize &size, const QMap> &formats, uint32_t flags); + bool checkGbmSurface(const QSize &size, const QMap> &formats, bool forceLinear); + bool createGbmSurface(const QSize &size, uint32_t format, const QVector &modifiers, bool forceLinear); + bool createGbmSurface(const QSize &size, const QMap> &formats, bool forceLinear); bool doesGbmSurfaceFit(GbmSurface *surf, const QSize &size, const QMap> &formats) const; bool doesShadowBufferFit(ShadowBuffer *buffer, const QSize &size, DrmPlane::Transformations renderOrientation, DrmPlane::Transformations bufferOrientation) const;