PDA

View Full Version : old problem with QGLContext and render pixmap



mickey
14th July 2006, 00:15
hi, I have an old problem with render pixmap; after gen pixmap called, my textures are destroyed and I can't understand why.


//inside a member of mainForm class
QPixmap qp
qp = myWidget1->renderPixmap(800, 600, FALSE);
qi=qp.convertToImage();
qi = qi.smoothScale(500,500);
qi.save(base_file+".png","PNG");

I know render pixmap do this: create a new contextGL call initializeGL(), resizeGL() an PaintGL(); after, it restore the previous context; but the previuos context is broken..also pixmap doesn't appear realistic: some textures are broken; but the texture broken on the final image image.jpg) and image on widgetGL aren't the same...
I tried to do:


myWidget1->initializeGL();
myWidget1->resizeGL(myWidget1->width(), myWidget1->height());
myWidget1->paintGL();

I thought this can see to me if some error in contextGL; but these 3 instrucion don't change the image in QGLWIdget....
After this, if I put a new texture on my image (ie on one object, so that call every gl function that initialize texttures), the prevoius context is restored and every textures are in the right place)
Help me, please; thanks

jacek
14th July 2006, 09:26
If I remember well, in initializeGL() you create new textures and store their IDs in member variables. If you call initializeGL() from a different context, you will loose information about textures from previous one. You must find a way to preserve those IDs between contexts (for example copy them somewhere or keep them on a stack).

mickey
14th July 2006, 10:35
sorry, I don't understand good but how copy it on the stack; thanks

jacek
14th July 2006, 11:14
I don't understand good but how copy it on the stack
If you have something like:
void GlWidget::initializeGL()
{
...
_textureId = generateTexture();
...
}then each time you invoke initializeGL() you will loose the previous value of _textureId member variable.

You can avoid that like this:

void GlWidget::renderPixmap(...)
{
int oldTextureId = _textureId;
QPixmap result( QGLWidget::renderPixmap( ... ) );
_textureId = oldTextureId;
return result;
}

mickey
14th July 2006, 12:00
sorry but I can't understand what's the textureID; but after I call genPixmap (now I put It inside myWidget class and don't change everythings), I call updateGL(),and everythings appear as before; then I think my way to put texture is ok.; i think is only a context problem....could you explain better what do you want to do with saving this texture ids?? thanks

jacek
14th July 2006, 12:05
could you explain better what do you want to do with saving this texture ids??
Could you post your initializeGL()? I might not remember your program well.

mickey
14th July 2006, 13:21
take it. thanks

jacek
14th July 2006, 13:30
What does plain.initGL() do?

mickey
14th July 2006, 13:35
it initialize every textures....gen tex, bind....plain it's an object and onto this I put the texture...

jacek
14th July 2006, 13:42
it initialize every textures....gen tex, bind....
That's the place where the problem is. Can I see it?

mickey
14th July 2006, 14:24
it's very complicated. Can I mail it you? thanks

jacek
14th July 2006, 14:44
Can I mail it you?
Yes, you can.

jacek
14th July 2006, 15:25
Here's the problematic part:
void Plain::initGL() {
...
glGenTextures(dimX*dimZ, tex);
glGenTextures(1, &lastTex);
...
glBindTexture(GL_TEXTURE_2D, lastTex );
...
glBindTexture(GL_TEXTURE_2D, tex[contite]);
...
}
Every time you invoke Plain::initGL() new textures are generated. The images are stored inside OpenGL context (represented by QGLContex) and your program receives only ID numbers of those textures (that's what you store in tex and lastTex).

Now if you invoke initGL() for the second time (within the same context), tex and lastTex will be filled with new values --- the old textures will be still in memory, but you won't be able to access them, since those variables will hold IDs of the new textures. It's not a big problem (except for the resource leak).

But what happens when you invoke initGL() within a different context (just like it happens during renderPixmap())? initGL() will generate new textures, that will be stored in a new context, and it will store their IDs in tex and lastTex (the same ones, since you have only one Plain object). Now when renderPixmap() ends, it destroys that temporary context and the new textures are destroyed too, but tex and lastTex still hold their IDs. The problem is that when you will try to draw something later, you will use invalid texture IDs.

You can solve this problem like this:
void GlWidget::renderPixmap(...)
{
plain.store();
QPixmap result( QGLWidget::renderPixmap( ... ) );
plain.restore();
return result;
}
...
void Plain::store()
{
// copy tex and lastTex values somewhere
// for example onto QValueStack
}

void Plain::restore()
{
// restore tex and lastTex values
}

mickey
15th July 2006, 15:24
I'm thinking to your solution...and other troubles arise: is there a way to clean the contextGL? (in the same way when app started)
then, I see that renderPixmap render my scene ok but don't render right texture multitextured; is it right? thanks

mickey
21st July 2006, 01:17
your solution is ok!! but when I save pixmap into a .jpg the texture multitextured appear gray oe black; if i don't use multitexture they appear ok! does depends it from qt3??Can i solve it? thanks
Furthermore: the objcet appear with same lines that they aren't visible in glWidget; eg: in square textured is visible a diagonal line (only in .jpg not in glWidget) what's it???