From aaf8ce16dfb258a48ea25209b6747f5d9f5a85b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 11 Jul 2016 10:53:04 +0200 Subject: [PATCH] [platforms/fbdev] Properly detect a BGR image format Summary: If the format of the framebuffer is BGR we cannot create an RGB image format from it - the rendering is incorrect. Unfortunately QImage does not support a BGR image format. To solve this problem we still use an RGB image format but on rendering the front buffer is rgbSwapped to convert the RGB image to a BGR image. BUG: 365243 FIXED-IN: 5.7.2 Test Plan: Tested on a neon kvm Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2134 --- plugins/platforms/fbdev/fb_backend.cpp | 16 +++++++++++----- plugins/platforms/fbdev/fb_backend.h | 9 +++++++++ .../fbdev/scene_qpainter_fb_backend.cpp | 2 +- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/plugins/platforms/fbdev/fb_backend.cpp b/plugins/platforms/fbdev/fb_backend.cpp index fc7ed42c78..370ad43da1 100644 --- a/plugins/platforms/fbdev/fb_backend.cpp +++ b/plugins/platforms/fbdev/fb_backend.cpp @@ -92,6 +92,7 @@ void FramebufferBackend::openFrameBuffer() } m_fd = fd; queryScreenInfo(); + initImageFormat(); setReady(true); emit screensQueried(); } @@ -153,9 +154,14 @@ void FramebufferBackend::unmap() } QImage::Format FramebufferBackend::imageFormat() const +{ + return m_imageFormat; +} + +void FramebufferBackend::initImageFormat() { if (m_fd < 0) { - return QImage::Format_Invalid; + return; } qCDebug(KWIN_FB) << "Bits Per Pixel: " << m_bitsPerPixel; @@ -178,7 +184,7 @@ QImage::Format FramebufferBackend::imageFormat() const m_green.offset == 8 && m_red.offset == 16) { qCDebug(KWIN_FB) << "Framebuffer format is RGB32"; - return QImage::Format_RGB32; + m_imageFormat = QImage::Format_RGB32; } else if (m_bitsPerPixel == 24 && m_red.length == 8 && m_green.length == 8 && @@ -187,7 +193,8 @@ QImage::Format FramebufferBackend::imageFormat() const m_green.offset == 8 && m_red.offset == 16) { qCDebug(KWIN_FB) << "Framebuffer Format is RGB888"; - return QImage::Format_RGB888; + m_bgr = true; + m_imageFormat = QImage::Format_RGB888; } else if (m_bitsPerPixel == 16 && m_red.length == 5 && m_green.length == 6 && @@ -196,10 +203,9 @@ QImage::Format FramebufferBackend::imageFormat() const m_green.offset == 5 && m_red.offset == 11) { qCDebug(KWIN_FB) << "Framebuffer Format is RGB16"; - return QImage::Format_RGB16; + m_imageFormat = QImage::Format_RGB16; } qCWarning(KWIN_FB) << "Framebuffer format is unknown"; - return QImage::Format_Invalid; } } diff --git a/plugins/platforms/fbdev/fb_backend.h b/plugins/platforms/fbdev/fb_backend.h index 7aee7eefc8..e888994722 100644 --- a/plugins/platforms/fbdev/fb_backend.h +++ b/plugins/platforms/fbdev/fb_backend.h @@ -71,10 +71,17 @@ public: return m_bitsPerPixel; } QImage::Format imageFormat() const; + /** + * @returns whether the imageFormat is BGR instead of RGB. + **/ + bool isBGR() const { + return m_bgr; + } private: void openFrameBuffer(); bool queryScreenInfo(); + void initImageFormat(); QSize m_resolution; QSize m_physicalSize; QByteArray m_id; @@ -91,6 +98,8 @@ private: quint32 m_bufferLength = 0; int m_bytesPerLine = 0; void *m_memory = nullptr; + QImage::Format m_imageFormat = QImage::Format_Invalid; + bool m_bgr = false; }; } diff --git a/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp b/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp index 732d5f31fe..ec311586c9 100644 --- a/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp +++ b/plugins/platforms/fbdev/scene_qpainter_fb_backend.cpp @@ -79,7 +79,7 @@ void FramebufferQPainterBackend::present(int mask, const QRegion &damage) return; } QPainter p(&m_backBuffer); - p.drawImage(QPoint(0, 0), m_renderBuffer); + p.drawImage(QPoint(0, 0), m_backend->isBGR() ? m_renderBuffer.rgbSwapped() : m_renderBuffer); } bool FramebufferQPainterBackend::usesOverlayWindow() const