PDA

View Full Version : QPixmap in thread



Talei
11th March 2013, 20:51
Hello
I want to convert QImage into QPixmap using QPixmap().convertFromImage(QImage) but the problem is that I have larg images, like 5k and that freezes Ui.

Currently I convert images in another thread, and here is my question:

is there any danger to create QPixamap in another thread if QPixmap is not accessed from non Ui thread - they are just created and stored in list?

Is there any better way to do that? I need QPixmap and not QImage because I need to display them in QGraphicsScene.

Regards

wysota
11th March 2013, 22:19
Yes, you can't create pixmaps in non-GUI threads. A potential solution is to tile the image so that you have smaller images that you can process in batches.

lanz
12th March 2013, 07:05
Technically you can, but you need to call XInitThreads, or pass AA_X11InitThreads to QApplication::setAttribute (). I did it and it worked... for a while :D
On another machine it simply breaks, for the reason I haven't yet researched.
So I made a fallback to QImage. I'm not very happy with performance though.
If there's a way for doing deferred rendering in another thread I'd like to hear about that :D

Talei
12th March 2013, 16:28
Well I did manage to convert it in another thread and that works fine, excluding warning all over the place for the QPixmap in non GUI thread.

QPixmap's are not thread safe so You can't use it in another thread.
But my question was related not to the accessing issue but to the thread affinity for the QPixmap's. So if I create object in thread A then that object lives in thread A. For the i.e. QImage its fine, but I don't know if thread affinity will conflict with QPixmaps.

AFAIK the reason is that only GUI thread has QPainterEngine active and that one is used to paint on QPixmaps. Depending on the server, i.e. X11, OGL etc. server strange thing can happens, especially on X11.

PS. Tilling won't work, because total time will be, in average, the same. Because the reason why I need QPixmap is that I will display them, and there in no big time difference between converting 1 time 5kx5k QImage and 5 times 1kx1k QImage. Of course from speed conversion point of view, not Ui freezing, with using 5x 1kx1k conversion help.

wysota
12th March 2013, 20:41
But my question was related not to the accessing issue but to the thread affinity for the QPixmap's.
QPixmap doesn't have any thread affinity. It's not a QObject. It simply relies on the platform dependent way to access graphical resources thus it has to be accessed from the UI thread. It may work for you today but it might as well fail tomorrow.


PS. Tilling won't work, because total time will be, in average, the same.
Total time will be the same but you can let your UI thread process events more frequently.

Talei
12th March 2013, 22:24
QPixmap -> QObject, yes, I was thinking of other "affinity" but I don't know if it is correct anyway.

So technically speaking if I just create QPixmap in another thread and don't display / access that qpixmap from non GUI thread, then It should always work? I mean why it shouldn't work, it's just created data in memory (on server side).

I was thinking that if QPixmap will be created in different thread, and if I use i.e. OpenGL as render engine, then that QPixmap will live on server side in a memory assigned to that thread and If that thread will case to exist then that memory will be freed? But I think that's wrong assumption and explicit deletion is needed of such data.

So the question is, can I create - and not use QPixmap - in non GUI thread and then only use it from main Ui thread? Or will that also produce "if'y" situation?

wysota
12th March 2013, 22:42
So technically speaking if I just create QPixmap in another thread and don't display / access that qpixmap from non GUI thread, then It should always work?
I don't think there are any guarantees like that. "Creating" the pixmap means resource allocation which is the place where all can fail.


I mean why it shouldn't work, it's just created data in memory (on server side).
That's exactly why. Because the server connection is "owned" by a different thread.

lanz
13th March 2013, 07:54
Well, that got me to think of interesting (or stupid :D) solution.
Maybe I can create another connection to server, thought it seems not a very cross-platform.
Another variant maybe to create two processes tied by TCP/Dbus/pipes.
I assuming of course that QPainter/QImage drawing is significantly slower than QPainter/QPixmap (latter using hardware acceleration), am I right?

wysota
13th March 2013, 09:22
Well, that got me to think of interesting (or stupid :D) solution.
Maybe I can create another connection to server, thought it seems not a very cross-platform.

As far as I understand how X11 works, there would be no way to use that pixmap using the other connection.


I assuming of course that QPainter/QImage drawing is significantly slower than QPainter/QPixmap (latter using hardware acceleration), am I right?
On X11 with real X11 drawing (and not the raster engine) you can only draw pixmaps (an image is converted to a pixmap before being drawn). With the raster engine (e.g. on Windows) I think it doesn't matter whether you use QPixmap or QImage. I'm not sure of that though.

lanz
13th March 2013, 09:43
As far as I understand how X11 works, there would be no way to use that pixmap using the other connection.
Yeah... I thought of speeding up painter draw calls, but seems like it cancels out by converting from pixmap at one connection, then recreating pixmap at the other.