Fix re-rendering of images when using partial updates

Partial updates trigger when the page is taking "too much" to render (>
500 ms).

When this happens we store a pixmap for the page, this meant that
Page::hasPixmap returned true, so when moving the viewport around we
would think that that page was already rendered, and thus needed no
rendering so we didn't add it to the list of requested pixmaps.

Then on document when seeing the new list of requested pixmaps we would
go and check and say "oh there's one request going on that we don't want
anymore, let's cancel it", so we would cancel the page that we actually
wanted (and clear the partial pixmap)

Then on the next scroll we would realize we did not have that page
pixmap and then request it again which since it's the current page would
immediately stop all other renders and start this one.

Then we would get a temporary pixmap and the loop of cancellations and
requesting again would keep happening as long as the user moved the
viewport.

We fix that my making hasPixmap return false if the pixmap we have is a
partial one, because that's what the function meant "forever" until we
recently introduced partial updates so all the calls to hasPixmap
actually mean "hasNonPartialPixmap"

BUGS: 418086
This commit is contained in:
Albert Astals Cid 2020-02-24 00:12:53 +01:00
parent a7876ca013
commit 81c005710c
3 changed files with 9 additions and 1 deletions

View file

@ -116,10 +116,12 @@ void PagePrivate::imageRotationDone( RotationJob * job )
PixmapObject &object = it.value();
(*object.m_pixmap) = QPixmap::fromImage( job->image() );
object.m_rotation = job->rotation();
object.m_isPartialPixmap = job->isPartialUpdate();
} else {
PixmapObject object;
object.m_pixmap = new QPixmap( QPixmap::fromImage( job->image() ) );
object.m_rotation = job->rotation();
object.m_isPartialPixmap = job->isPartialUpdate();
m_pixmaps.insert( job->observer(), object );
}
@ -235,6 +237,9 @@ bool Page::hasPixmap( DocumentObserver *observer, int width, int height, const N
if ( width == -1 || height == -1 )
return true;
if ( it.value().m_isPartialPixmap )
return false;
const QPixmap *pixmap = it.value().m_pixmap;
return (pixmap->width() == width && pixmap->height() == height);
@ -556,6 +561,7 @@ void PagePrivate::setPixmap( DocumentObserver *observer, QPixmap *pixmap, const
}
it.value().m_pixmap = pixmap;
it.value().m_rotation = m_rotation;
it.value().m_isPartialPixmap = isPartialPixmap;
} else {
// it can happen that we get a setPixmap while closing and thus the page controller is gone
if ( m_doc->m_pageController )

View file

@ -141,8 +141,9 @@ class OKULARCORE_EXPORT Page
void setBoundingBox( const NormalizedRect& bbox );
/**
* Returns whether the page of size @p width x @p height has a @p pixmap
* Returns whether the page of size @p width x @p height has a @p pixmap
* in the region given by @p rect for the given @p observer
* If there is a partially rendered pixmap the answer is false.
*/
bool hasPixmap( DocumentObserver *observer, int width = -1, int height = -1, const NormalizedRect &rect = NormalizedRect() ) const;

View file

@ -146,6 +146,7 @@ class PagePrivate
public:
QPixmap *m_pixmap = nullptr;
Rotation m_rotation;
bool m_isPartialPixmap = false;
};
QMap< DocumentObserver*, PixmapObject > m_pixmaps;
QMap< const DocumentObserver*, TilesManager *> m_tilesManagers;