PDA

View Full Version : QGLWidget, QPainter and shared contexts



bamboo
10th April 2007, 15:21
Hi there !

I'm having trouble using a QPainter (specifically drawing QPixmap) on a QGLWidget.

Here's my setup :
I have an application with two QGLWidget sharing the same GL context (this is important).
I then use a QPainter to draw QPixmaps over the GL rendering.
Everything is fine except memory usage increases indefinitely. This won't happen if i don't call the QPainter::drawPixmap() function.

I went through Qt's code and noticed that they use a cache system maintaining GL textures associated to QPixmap. The thing is that when Qt decides to remove a GL texture from the cache, if the context used to create that texture is shared (that's true in my case) Qt won't destory the underlying GL texture (glDeleteTextures) resulting in leaving unreachable GL textures in memory.
I modified Qt's code to skip the test and it runs just fine (memory usage won't increase).

As those GL textures are internally created by Qt and as I couldn't find any function to access them, I can't do much about it ...

So I wondered if any of you had ever encountered the issue, or if I missed something, or if i did something the wrong way ...

I forgot to mention that some of the QPixmap I draw are updated quite often and that's why the cache has to delete objects.

Thanks !

PS: a few references in the code if you're interested :
the Qt's wrapper class around GL texture objects. Instance of those are being held in the cache.
file qgl.cpp, line 1288 (Qt 4.2.0 open source edition):

class QGLTexture {
public:
QGLTexture(const QGLContext *ctx, GLuint tx_id, qint64 _qt_id, bool _clean = false)
: context(ctx), id(tx_id), qt_id(_qt_id), clean(_clean) {}
~QGLTexture() {
if (!context->isSharing()) // <--- THERE
glDeleteTextures(1, &id);
}

const QGLContext *context;
GLuint id;
qint64 qt_id;
bool clean;
};

Deleting such an object won't release the underlying GL texture if context is shared ...

wysota
13th April 2007, 13:23
You can either report a bug and/or try to reuse the same texture for a new pixmap (I understand the problem is that the pixmap changes which causes memory usage to grow) and draw directly using GL code.

bamboo
16th April 2007, 09:59
Thanks,

I reported a bug to trolltech last week about that.
But I can't reuse the same GL texture as I don't have access to it.
For now i just don't use a QPainter to draw on QGLWidgets. I draw everything I need in an offscreen QPixmap and then use my own code to upload and draw it with OpenGL.

I'll post here references to the bug I reported if any are interested.

wysota
16th April 2007, 10:20
What do you mean you don't have access to it? So what calls BindTexture()?

bamboo
16th April 2007, 10:41
Qt does.
I never dealt directly with OpenGL. I just used the QPainter and drawPixmap().
Internally drawPixmap() creates GL textures for each of my QPixmap and store them in the cache. Whenever a QPixmap is modified, a new GL texture is associated to it. When the cache hits its size limit, Qt deletes GL textures but as my GL context is shared, glDeleteTexture() is never called (but the Qt wrapper around GL textures is deleted from the cache).

Basically this is what I was doing :



void draw_overlays(QGLWidget *p_GL)
{
QPainter l_Painter(p_GL);

// my overlays are QPixmaps
// some of them can be updated often
for_each_of_my_overlays()
{
// this will internally create a GL texture for the QPixmap
// reusing the texture if the QPixmap is the same (cache system)
l_Painter->drawPixmap(l_Overlay);
}
}


I hope I'm clear enough ;)

edit: I think I understand what you mean. I don't use QGLWidget::bindTexture() neither QGLContext::bindTexture() but I noticed in the docs that if the context is shared the GL texture won't be destroyed. But in my case, Qt creates GL texture, not me.

wysota
16th April 2007, 10:50
Ok, but this is an overlay. You do have some actual GL code underneath. So you can make a plane, place it orthogonal to the screen and instead of using QPainter simply apply a texture to the plane.

bamboo
16th April 2007, 10:55
Yep, that's what I do now to overcome this ;)
But using QPainter would have been "cleaner" and easier for me as it is designed fot this.
Anyway I reported the bug to Trolltech as I don't think this is a normal behavior ...
Thanks !

bamboo
17th April 2007, 19:11
Hi again,

for those who might be interested, the bug has been verified by Qt's team and has been assigned #158971.
http://www.trolltech.com/developer/task-tracker/index_html?method=entry&id=158971

Have a nice day !