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);
_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)
/*
* 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());
}
return _framebuffer;
}

View File

@ -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;

View File

@ -11,6 +11,10 @@
* 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 <qpa/qplatformscreen.h>
@ -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 &region, 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)

View File

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