From 2f7167fab29fe448b8ff831c0e731869bf7d411f Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Thu, 14 Aug 2014 17:09:12 +0200 Subject: [PATCH] Qt5: use double buffering Fixes #1229. --- .../nitpicker/qnitpickerplatformwindow.cpp | 22 +++++++-- .../nitpicker/qnitpickerplatformwindow.h | 1 + .../nitpicker/qnitpickerwindowsurface.cpp | 45 ++++++++++++++++--- .../nitpicker/qnitpickerwindowsurface.h | 1 + 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp index 42ec464ef3..363cc0f891 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.cpp @@ -175,6 +175,8 @@ void QNitpickerPlatformWindow::_adjust_and_set_geometry(const QRect &rect) Framebuffer::Mode::RGB565); _nitpicker_session.buffer(mode, false); + _framebuffer_changed = true; + emit framebuffer_changed(); } @@ -183,6 +185,7 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_ : QPlatformWindow(window), _framebuffer_session(_nitpicker_session.framebuffer_session()), _framebuffer(0), + _framebuffer_changed(false), _view_handle(_create_view()), _input_session(_nitpicker_session.input_session()), _timer(this), @@ -535,12 +538,23 @@ bool QNitpickerPlatformWindow::frameStrutEventsEnabled() const unsigned char *QNitpickerPlatformWindow::framebuffer() { if (qnpw_verbose) - qDebug() << "QNitpickerPlatformWindow::framebuffer()"; + qDebug() << "QNitpickerPlatformWindow::framebuffer()" << _framebuffer; - if (_framebuffer) - Genode::env()->rm_session()->detach(_framebuffer); + /* + * The new framebuffer is acquired in this function to avoid a time span when + * the nitpicker buffer would be black and not refilled yet by Qt. + */ + + if (_framebuffer_changed) { + + _framebuffer_changed = false; + + if (_framebuffer != 0) + Genode::env()->rm_session()->detach(_framebuffer); + + _framebuffer = Genode::env()->rm_session()->attach(_framebuffer_session.dataspace()); + } - _framebuffer = Genode::env()->rm_session()->attach(_framebuffer_session.dataspace()); return _framebuffer; } diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h index df2f4c2a78..235356f47d 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerplatformwindow.h @@ -40,6 +40,7 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow Nitpicker::Connection _nitpicker_session; Framebuffer::Session_client _framebuffer_session; unsigned char *_framebuffer; + bool _framebuffer_changed; Nitpicker::Session::View_handle _view_handle; Input::Session_client _input_session; Input::Event *_ev_buf; diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp index 86ff16aa7d..4fa9aca0f7 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.cpp @@ -11,6 +11,10 @@ * under the terms of the GNU General Public License version 2. */ +/* Genode includes */ +#include + +/* Qt includes */ #include #include @@ -26,7 +30,7 @@ static const bool verbose = false; QT_BEGIN_NAMESPACE QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window) - : QPlatformBackingStore(window), _framebuffer_changed(true) + : QPlatformBackingStore(window), _backbuffer(0), _framebuffer_changed(true) { //qDebug() << "QNitpickerWindowSurface::QNitpickerWindowSurface:" << (long)this; @@ -36,6 +40,7 @@ QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window) QNitpickerWindowSurface::~QNitpickerWindowSurface() { + qFree(_backbuffer); } QPaintDevice *QNitpickerWindowSurface::paintDevice() @@ -55,7 +60,10 @@ QPaintDevice *QNitpickerWindowSurface::paintDevice() */ QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); QRect geo = _platform_window->geometry(); - _image = QImage(_platform_window->framebuffer(), geo.width(), geo.height(), 2*geo.width(), format); + unsigned int const bytes_per_pixel = QGuiApplication::primaryScreen()->depth() / 8; + qFree(_backbuffer); + _backbuffer = (unsigned char*)qMalloc(geo.width() * geo.height() * bytes_per_pixel); + _image = QImage(_backbuffer, geo.width(), geo.height(), geo.width() * bytes_per_pixel, format); if (verbose) qDebug() << "QNitpickerWindowSurface::paintDevice(): w =" << geo.width() << ", h =" << geo.height(); @@ -80,10 +88,35 @@ void QNitpickerWindowSurface::flush(QWindow *window, const QRegion ®ion, cons << ", offset =" << offset << ")"; - _platform_window->refresh(region.boundingRect().x() + offset.x(), - region.boundingRect().y() + offset.y(), - region.boundingRect().width(), - region.boundingRect().height()); + unsigned int const bytes_per_pixel = _image.depth() / 8; + + for (int i = 0; i < region.rects().size(); i++) { + + QRect rect(region.rects()[i]); + + /* + * It happened that after resizing a window, the given flush region was + * bigger than the current window size, so clipping is necessary here. + */ + + rect &= _image.rect(); + + unsigned int buffer_offset = ((rect.y() + offset.y()) * _image.bytesPerLine()) + + ((rect.x() + offset.x()) * bytes_per_pixel); + + blit(_image.bits() + buffer_offset, + _image.bytesPerLine(), + _platform_window->framebuffer() + buffer_offset, + _image.bytesPerLine(), + rect.width() * bytes_per_pixel, + rect.height()); + + _platform_window->refresh(rect.x() + offset.x(), + rect.y() + offset.y(), + rect.width(), + rect.height()); + } + } void QNitpickerWindowSurface::resize(const QSize &size, const QRegion &staticContents) diff --git a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.h b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.h index e90a8162fb..214b50d658 100644 --- a/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.h +++ b/repos/libports/src/lib/qt5/qtbase/src/plugins/platforms/nitpicker/qnitpickerwindowsurface.h @@ -28,6 +28,7 @@ class QNitpickerWindowSurface : public QObject, public QPlatformBackingStore private: QNitpickerPlatformWindow *_platform_window; + unsigned char *_backbuffer; QImage _image; bool _framebuffer_changed;