Qt5: use double buffering

Fixes #1229.
This commit is contained in:
Christian Prochaska
2014-08-14 17:09:12 +02:00
committed by Norman Feske
parent 85744a8308
commit 2f7167fab2
4 changed files with 59 additions and 10 deletions

View File

@ -175,6 +175,8 @@ void QNitpickerPlatformWindow::_adjust_and_set_geometry(const QRect &rect)
Framebuffer::Mode::RGB565); Framebuffer::Mode::RGB565);
_nitpicker_session.buffer(mode, false); _nitpicker_session.buffer(mode, false);
_framebuffer_changed = true;
emit framebuffer_changed(); emit framebuffer_changed();
} }
@ -183,6 +185,7 @@ QNitpickerPlatformWindow::QNitpickerPlatformWindow(QWindow *window, Genode::Rpc_
: QPlatformWindow(window), : QPlatformWindow(window),
_framebuffer_session(_nitpicker_session.framebuffer_session()), _framebuffer_session(_nitpicker_session.framebuffer_session()),
_framebuffer(0), _framebuffer(0),
_framebuffer_changed(false),
_view_handle(_create_view()), _view_handle(_create_view()),
_input_session(_nitpicker_session.input_session()), _input_session(_nitpicker_session.input_session()),
_timer(this), _timer(this),
@ -535,12 +538,23 @@ bool QNitpickerPlatformWindow::frameStrutEventsEnabled() const
unsigned char *QNitpickerPlatformWindow::framebuffer() unsigned char *QNitpickerPlatformWindow::framebuffer()
{ {
if (qnpw_verbose) 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; return _framebuffer;
} }

View File

@ -40,6 +40,7 @@ class QNitpickerPlatformWindow : public QObject, public QPlatformWindow
Nitpicker::Connection _nitpicker_session; Nitpicker::Connection _nitpicker_session;
Framebuffer::Session_client _framebuffer_session; Framebuffer::Session_client _framebuffer_session;
unsigned char *_framebuffer; unsigned char *_framebuffer;
bool _framebuffer_changed;
Nitpicker::Session::View_handle _view_handle; Nitpicker::Session::View_handle _view_handle;
Input::Session_client _input_session; Input::Session_client _input_session;
Input::Event *_ev_buf; Input::Event *_ev_buf;

View File

@ -11,6 +11,10 @@
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
/* Genode includes */
#include <blit/blit.h>
/* Qt includes */
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <qpa/qplatformscreen.h> #include <qpa/qplatformscreen.h>
@ -26,7 +30,7 @@ static const bool verbose = false;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window) QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window)
: QPlatformBackingStore(window), _framebuffer_changed(true) : QPlatformBackingStore(window), _backbuffer(0), _framebuffer_changed(true)
{ {
//qDebug() << "QNitpickerWindowSurface::QNitpickerWindowSurface:" << (long)this; //qDebug() << "QNitpickerWindowSurface::QNitpickerWindowSurface:" << (long)this;
@ -36,6 +40,7 @@ QNitpickerWindowSurface::QNitpickerWindowSurface(QWindow *window)
QNitpickerWindowSurface::~QNitpickerWindowSurface() QNitpickerWindowSurface::~QNitpickerWindowSurface()
{ {
qFree(_backbuffer);
} }
QPaintDevice *QNitpickerWindowSurface::paintDevice() QPaintDevice *QNitpickerWindowSurface::paintDevice()
@ -55,7 +60,10 @@ QPaintDevice *QNitpickerWindowSurface::paintDevice()
*/ */
QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); QImage::Format format = QGuiApplication::primaryScreen()->handle()->format();
QRect geo = _platform_window->geometry(); 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) if (verbose)
qDebug() << "QNitpickerWindowSurface::paintDevice(): w =" << geo.width() << ", h =" << geo.height(); qDebug() << "QNitpickerWindowSurface::paintDevice(): w =" << geo.width() << ", h =" << geo.height();
@ -80,10 +88,35 @@ void QNitpickerWindowSurface::flush(QWindow *window, const QRegion &region, cons
<< ", offset =" << offset << ", offset =" << offset
<< ")"; << ")";
_platform_window->refresh(region.boundingRect().x() + offset.x(), unsigned int const bytes_per_pixel = _image.depth() / 8;
region.boundingRect().y() + offset.y(),
region.boundingRect().width(), for (int i = 0; i < region.rects().size(); i++) {
region.boundingRect().height());
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) void QNitpickerWindowSurface::resize(const QSize &size, const QRegion &staticContents)

View File

@ -28,6 +28,7 @@ class QNitpickerWindowSurface : public QObject, public QPlatformBackingStore
private: private:
QNitpickerPlatformWindow *_platform_window; QNitpickerPlatformWindow *_platform_window;
unsigned char *_backbuffer;
QImage _image; QImage _image;
bool _framebuffer_changed; bool _framebuffer_changed;