I am trying to implemente a CoverFlow like effect using a QGLWidget, the problem is the texture loading process.
I have a worker (QThread) for loading images from disk, and the main thread checks for new loaded images, if it finds any then uses bindTexture for loading them into QGLContext. While the texture is being bound, the main thread is blocked, so I have a fps drop.
What is the right way to do this?
Binding in the main thread (single
QGLWidgetsolution):decide on maximum texture size. You could decide it based on maximum possible widget size for example. Say you know that the widget can be at most (approximately) 800×600 pixels and the largest cover visible has 30 pixels margins up and down and 1:2 aspect ratio -> 600-2*30 = 540 -> maximum size of the cover is 270×540, e.g. stored in
m_maxCoverSize.scale the incoming images to that size in the loader thread. It doesn’t make sense to bind larger textures and the larger it is, the longer it’ll take to upload to the graphics card. Use
QImage::scaled(m_maxCoverSize, Qt::KeepAspectRatio)to scale loaded image and pass it to the main thread.limit the number of textures or better time spent binding them per frame. I.e. remember the time at which you started binding textures (e.g.
QTime bindStartTime😉 and after binding each texture do:if (bindStartTime.elapsed() > BIND_TIME_LIMIT)
break;
BIND_TIME_LIMITwould depend on frame rate you want to keep. But of course if binding each one texture takes much longer thanBIND_TIME_LIMITyou haven’t solved anything.You might still experience framerate drop while loading images though on slower machines / graphics cards. The rest of the code should be prepared to live with it (e.g. use actual time to drive animation).
Alternative solution is to bind in a separate thread (using a second invisible
QGLWidget, see documentation):